Skip to content

Commit 65d4bcf

Browse files
authored
Merge pull request #1577 from fvitt/tuvx_builds
cam6_4_182: Updates to CAM build of TUV-X lib
2 parents 9e9c137 + 4525eef commit 65d4bcf

11 files changed

Lines changed: 236 additions & 103 deletions

File tree

bld/build-namelist

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,15 @@ if (not $waccm_phys) {
750750
add_default($nl, 'p_bot_for_radmrg');
751751
}
752752

753+
# Check TUV-X configuration
754+
my $tuvx_active = $nl->get_value('tuvx_active');
755+
if ($tuvx_active =~ /$TRUE/io) {
756+
my $tuvx_config = $cfg->get('tuvx');
757+
if (!$tuvx_config) {
758+
die "$ProgName - ERROR: must use -tuvx CAM configure flag \n";
759+
}
760+
}
761+
753762
# Solar irradiance
754763

755764
# First check that solar_const and solar_irrad_data_file are not both defined

bld/config_files/definition.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ Option to turn on waccmx thermosphere/ionosphere extension: 0 => no, 1 => yes
5959
<entry id="ext_co2_cool" valid_values="0,1" value="0">
6060
Option to turn on extended non-LTE CO2 cooling: 0 => no, 1 => yes
6161
</entry>
62+
<entry id="tuvx" valid_values="0,1" value="0">
63+
Option to build TUV-X library: 0 => no, 1 => yes
64+
</entry>
6265
<entry id="ionosphere" valid_values="none,wxie" value="none">
6366
Ionosphere model used in WACCMX.
6467
</entry>

bld/configure

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ OPTIONS
107107
-psubcols <n> Maximum number of sub-columns in a run - set to 1 if not using sub-columns (default)
108108
-rad <name> Specify the radiation package [rrtmg | rrtmgp | rrtmgp_gpu | camrt]
109109
-silhs Switch on SILHS.
110+
-tuvx Switch to build TUV-X library
110111
-usr_mech_infile Path and file name of the user supplied chemistry mechanism file.
111112
-waccm_phys Switch enables the use of WACCM physics in any chemistry configuration.
112113
The user does not need to set this if one of the waccm chemistry options
@@ -305,6 +306,7 @@ GetOptions(
305306
"waccm_phys" => \$opts{'waccm_phys'},
306307
"waccmx" => \$opts{'waccmx'},
307308
"ext_co2_cool" => \$opts{'ext_co2_cool'},
309+
"tuvx" => \$opts{'tuvx'},
308310
) or usage();
309311

310312
# Give usage message.
@@ -717,6 +719,12 @@ if (defined $opts{'ext_co2_cool'}) {
717719
}
718720
my $ext_co2_cool = $cfg_ref->get('ext_co2_cool');
719721

722+
# TUV-x option
723+
if (defined $opts{'tuvx'}) {
724+
$cfg_ref->set('tuvx', $opts{'tuvx'});
725+
}
726+
my $tuvx = $cfg_ref->get('tuvx');
727+
720728
#-----------------------------------------------------------------------------------------------
721729

722730
# Prognostic species package(s)
@@ -1788,6 +1796,11 @@ if ($ext_co2_cool) {
17881796
$cfg_cppdefs .= ' -DEXT_CO2_COOL';
17891797
}
17901798

1799+
# TUV-X
1800+
if ($tuvx) {
1801+
$cfg_cppdefs .= ' -DTUVX';
1802+
}
1803+
17911804
# PIO
17921805
my $pio2_build = (defined $opts{'pio2'}) ? 1 : 0;
17931806

@@ -1864,7 +1877,7 @@ if ($cosp) {
18641877
$ldflags .= " -L$cosp_libdir -lrttov13_wrapper -lrttov13_mw_scatt -lrttov13_brdf_atlas -lrttov13_emis_atlas -lrttov13_other -lrttov13_parallel -lrttov13_coef_io -lrttov13_hdf -lrttov13_main ";
18651878
$cfg_ref->set('ldflags', $ldflags);
18661879
print "Adding rttov libraries as dependencies in ldflags.\n";
1867-
}
1880+
}
18681881
# Create the COSP Makefile from a template and copy it into the cosp bld directory
18691882
if ($print) { print "creating $cosp_libdir/Makefile\n"; }
18701883
write_cosp_makefile("$cfgdir/../src/physics/cosp2/Makefile.in", "$cosp_libdir/Makefile");

cime_config/buildlib

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ create the cam library
66
# pylint: disable=multiple-imports, wrong-import-position, wildcard-import
77
# pylint: disable=unused-wildcard-import, bad-whitespace, too-many-locals
88
# pylint: disable=invalid-name
9-
import sys, os, filecmp, shutil
9+
import sys, os, filecmp, shutil, re
1010
from glob import glob
1111

1212
_CIMEROOT = os.environ.get("CIMEROOT")
@@ -232,60 +232,76 @@ def _build_tuvx(caseroot, libroot, bldroot):
232232
# Builds the TUV-x library and updates the case variables used to set the
233233
# include paths and linked libraries
234234

235-
with Case(caseroot) as case:
236-
bldpath = os.path.join(bldroot, "tuv-x")
237-
if not os.path.exists(bldpath):
238-
os.makedirs(bldpath)
239-
srcpath = os.path.abspath(os.path.join(case.get_value("SRCROOT"), \
240-
"libraries", "tuv-x", ""))
241-
logger.info("Building TUV-x in {} from source in {}\n".format(bldpath, srcpath))
242-
243-
arg_dict = _cmake_default_args(caseroot)
244-
cmake_args = "-DCMAKE_VERBOSE_MAKEFILE=ON "
245-
if case.get_value("MPILIB") != "mpi-serial":
246-
cmake_args += "-DTUVX_ENABLE_MPI:BOOL=TRUE "
247-
cmake_args += "-DCMAKE_BUILD_TYPE=Debug "
248-
cmake_args += "-DCMAKE_Fortran_COMPILER=mpif90 "
249-
cmake_args += "-DCMAKE_C_COMPILER=mpicc "
250-
cmake_args += "-DCMAKE_CXX_COMPILER=mpicxx "
251-
cmake_args += "-DCMAKE_Fortran_COMPILER_WORKS=1 "
252-
cmake_args += "-DCMAKE_C_COMPILER_WORKS=1 "
253-
cmake_args += "-DCMAKE_CXX_COMPILER_WORKS=1 "
254-
if (case.get_value("MACH") == "izumi") :
255-
cmake_args += f"-DCMAKE_PREFIX_PATH={arg_dict['NETCDF_PATH']} "
256-
cmake_args += f"-DCMAKE_IGNORE_PATH={os.environ.get('PYTHONHOME')} "
257-
if (case.get_value("MACH") == "izumi") and (case.get_value('COMPILER') == "nag") :
258-
cmake_args += "-DCMAKE_Fortran_FLAGS='-C=all -g ' "
259-
else :
260-
cmake_args += f"-DCMAKE_Fortran_FLAGS='{arg_dict['FFLAGS']}' "
261-
cmake_args += f"-DCMAKE_INSTALL_PREFIX='{libroot}' "
262-
cmake_args += "-DTUVX_ENABLE_TESTS=OFF "
263-
cmake_args += "-DTUVX_ENABLE_COVERAGE=OFF "
264-
cmake_args += "-DTUVX_BUILD_CLI=OFF "
265-
cmake_args += f"-DTUVX_INSTALL_INCLUDE_DIR='{_tuvx_include_dir(libroot)}' "
266-
cmake_args += f"-DTUVX_INSTALL_MOD_DIR='{_tuvx_include_dir(libroot)}' "
267-
cmake_args += srcpath
268-
269-
_run_cmd(f"cmake {cmake_args}", bldpath)
270-
_run_cmd(case.get_value('GMAKE'), bldpath)
271-
_run_cmd(f"{case.get_value('GMAKE')} install", bldpath)
272-
273-
# add TUV-x to include paths
274-
incldir = os.environ.get('USER_INCLDIR')
275-
if incldir is None:
276-
incldir = ''
277-
os.environ['USER_INCLDIR'] = incldir + \
278-
f" -I{_tuvx_include_dir(libroot)} "
279-
280-
# create symlink to library in folder CIME expects libraries to be in
281-
dst = os.path.join(libroot, "libtuvx.a")
282-
if os.path.isfile(dst):
283-
os.remove(dst)
284-
os.symlink(_tuvx_lib_path(libroot), dst)
285-
dst = os.path.join(libroot, "libyaml-cpp.a")
286-
if os.path.isfile(dst):
287-
os.remove(dst)
288-
os.symlink(_yaml_cpp_lib_path(libroot), dst)
235+
with Case(caseroot, read_only=False) as case:
236+
config_opts = case.get_value("CAM_CONFIG_OPTS")
237+
238+
# Remove any TUV-x link options set by a previous build, so that
239+
# re-building the case does not accumulate duplicate or stale
240+
# options in CAM_LINKED_LIBS:
241+
linked_libs = case.get_value("CAM_LINKED_LIBS",
242+
subgroup="build_component_cam")
243+
tuvx_link_opts = " -ltuvx -lyaml-cpp"
244+
new_linked_libs = re.sub(r"\s*-ltuvx -lyaml-cpp", "", linked_libs)
245+
if "-tuvx" in config_opts:
246+
bldpath = os.path.join(bldroot, "tuv-x")
247+
if not os.path.exists(bldpath):
248+
os.makedirs(bldpath)
249+
srcpath = os.path.abspath(os.path.join(case.get_value("SRCROOT"), \
250+
"libraries", "tuv-x", ""))
251+
logger.info("Building TUV-x in {} from source in {}\n".format(bldpath, srcpath))
252+
253+
arg_dict = _cmake_default_args(caseroot)
254+
cmake_args = "-DCMAKE_VERBOSE_MAKEFILE=ON "
255+
if case.get_value("MPILIB") != "mpi-serial":
256+
cmake_args += "-DTUVX_ENABLE_MPI:BOOL=TRUE "
257+
cmake_args += "-DCMAKE_BUILD_TYPE=Debug "
258+
cmake_args += "-DCMAKE_Fortran_COMPILER=mpif90 "
259+
cmake_args += "-DCMAKE_C_COMPILER=mpicc "
260+
cmake_args += "-DCMAKE_CXX_COMPILER=mpicxx "
261+
cmake_args += "-DCMAKE_Fortran_COMPILER_WORKS=1 "
262+
cmake_args += "-DCMAKE_C_COMPILER_WORKS=1 "
263+
cmake_args += "-DCMAKE_CXX_COMPILER_WORKS=1 "
264+
cmake_args += "-DCMAKE_DISABLE_FIND_PACKAGE_yaml-cpp=1 "
265+
if (case.get_value("MACH") == "izumi") :
266+
cmake_args += f"-DCMAKE_PREFIX_PATH={arg_dict['NETCDF_PATH']} "
267+
if (case.get_value("MACH") == "izumi") and (case.get_value('COMPILER') == "nag") :
268+
cmake_args += "-DCMAKE_Fortran_FLAGS='-C=all -g ' "
269+
else :
270+
cmake_args += f"-DCMAKE_Fortran_FLAGS='{arg_dict['FFLAGS']}' "
271+
cmake_args += f"-DCMAKE_INSTALL_PREFIX='{libroot}' "
272+
cmake_args += "-DTUVX_ENABLE_TESTS=OFF "
273+
cmake_args += "-DTUVX_ENABLE_COVERAGE=OFF "
274+
cmake_args += "-DTUVX_BUILD_CLI=OFF "
275+
cmake_args += f"-DTUVX_INSTALL_INCLUDE_DIR='{_tuvx_include_dir(libroot)}' "
276+
cmake_args += f"-DTUVX_INSTALL_MOD_DIR='{_tuvx_include_dir(libroot)}' "
277+
cmake_args += srcpath
278+
279+
_run_cmd(f"cmake {cmake_args}", bldpath)
280+
_run_cmd(case.get_value('GMAKE'), bldpath)
281+
_run_cmd(f"{case.get_value('GMAKE')} install", bldpath)
282+
283+
# add TUV-x to include paths
284+
incldir = os.environ.get('USER_INCLDIR')
285+
if incldir is None:
286+
incldir = ''
287+
os.environ['USER_INCLDIR'] = incldir + \
288+
f" -I{_tuvx_include_dir(libroot)} "
289+
290+
# create symlink to library in folder CIME expects libraries to be in
291+
dst = os.path.join(libroot, "libtuvx.a")
292+
if os.path.isfile(dst):
293+
os.remove(dst)
294+
os.symlink(_tuvx_lib_path(libroot), dst)
295+
dst = os.path.join(libroot, "libyaml-cpp.a")
296+
if os.path.isfile(dst):
297+
os.remove(dst)
298+
os.symlink(_yaml_cpp_lib_path(libroot), dst)
299+
300+
# Add TUVX to CAM linked library list:
301+
new_linked_libs = tuvx_link_opts.strip() + " " + new_linked_libs
302+
303+
if new_linked_libs != linked_libs:
304+
case.set_value("CAM_LINKED_LIBS", new_linked_libs)
289305

290306
###############################################################################
291307
def _tuvx_include_dir(libroot):

cime_config/buildnml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ def buildnml(case, caseroot, compname):
6565
"Gregorian calendar (modifier _cG) cannot be used with spinup compset \n {}".format(COMPSET)
6666
)
6767

68-
tuvx_data_src = os.path.join(srcroot, "libraries", "tuv-x", "data")
68+
if '-tuvx' in CAM_CONFIG_OPTS:
69+
tuvx_data_src = os.path.join(srcroot, "libraries", "tuv-x", "data")
6970

7071
testsrc = os.path.join(srcroot, "components", "cam")
7172
if os.path.exists(testsrc):
@@ -237,10 +238,11 @@ def buildnml(case, caseroot, compname):
237238
shutil.copy(file1,file2)
238239

239240
# Copy TUV-x data to rundir
240-
dest_data = os.path.join(rundir, "data")
241-
if os.path.exists(dest_data):
242-
shutil.rmtree(dest_data)
243-
shutil.copytree(tuvx_data_src, dest_data)
241+
if '-tuvx' in CAM_CONFIG_OPTS:
242+
dest_data = os.path.join(rundir, "data")
243+
if os.path.exists(dest_data):
244+
shutil.rmtree(dest_data)
245+
shutil.copytree(tuvx_data_src, dest_data)
244246

245247
###############################################################################
246248
def _main_func():

cime_config/config_component.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@
230230
<entry id="CAM_LINKED_LIBS">
231231
<type>char</type>
232232
<valid_values></valid_values>
233-
<default_value>-ltuvx -lyaml-cpp -lstdc++</default_value>
233+
<default_value>-lstdc++</default_value>
234234
<group>build_component_cam</group>
235235
<file>env_build.xml</file>
236236
<desc>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
./xmlchange CAM_CONFIG_OPTS=" -phys cam4 -rad rrtmg -chem waccm_ma_sulfur -carma mixed_sulfate"
1+
./xmlchange CAM_CONFIG_OPTS=" -phys cam4 -rad rrtmg -chem waccm_ma_sulfur -carma mixed_sulfate -tuvx"
22
./xmlchange ROF_NCPL=\$ATM_NCPL
33
./xmlchange GLC_NCPL=\$ATM_NCPL
44
./xmlchange RUN_STARTDATE="0001-01-01"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
./xmlchange --append CAM_CONFIG_OPTS="-tuvx"
12
./xmlchange ROF_NCPL=\$ATM_NCPL
23
./xmlchange GLC_NCPL=\$ATM_NCPL
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
./xmlchange ROF_NCPL=\$ATM_NCPL
2-
./xmlchange CAM_CONFIG_OPTS="-phys cam6 -age_of_air_trcs -chem waccm_ma_mam4 -ext_co2_cool"
2+
./xmlchange CAM_CONFIG_OPTS="-phys cam6 -age_of_air_trcs -chem waccm_ma_mam4 -ext_co2_cool -tuvx"

doc/ChangeLog

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,84 @@
1+
===============================================================
2+
3+
Tag name: cam6_4_182
4+
Originator(s): fvitt
5+
Date: 16 Jun 2026
6+
One-line Summary: Updates to CAM's build of TUV-X library
7+
Github PR URL: https://github.com/ESCOMP/CAM/pull/1577
8+
9+
Purpose of changes (include the issue number and title text for each relevant GitHub issue):
10+
11+
Build TUV-X library only in cases where TUV-X is used. Configure
12+
switch -tuvx has been added to CAM_CONFIG_OPTS which activates
13+
the build of the TUV-X library.
14+
15+
Address issues:
16+
#1537: TUV-x build issue when users have Conda environments active
17+
https://github.com/ESCOMP/CAM/issues/1570
18+
19+
#1570: TUV-x copies input files to run directory regardless of whether TUV-x is active
20+
https://github.com/ESCOMP/CAM/issues/1570
21+
22+
Describe any changes made to build system:
23+
Changes TUV-X library build as described above
24+
25+
Describe any changes made to the namelist: N/A
26+
27+
List any changes to the defaults for the boundary datasets: N/A
28+
29+
Describe any substantial timing or memory changes: N/A
30+
31+
Code reviewed by: jimmielin cacraigucar
32+
33+
List all files eliminated: N/A
34+
35+
List all files added and what they do: N/A
36+
37+
List all existing files that have been modified, and describe the changes:
38+
39+
M bld/build-namelist
40+
- error out if tuvx_active is TRUE and not configured for TUV-X
41+
42+
M bld/config_files/definition.xml
43+
M bld/configure
44+
- add "-tuvx" configure switch -- define "TUVX" CPP def
45+
46+
M cime_config/buildlib
47+
- build TUV-X lib only if "-tuvx" is included in CAM_CONFIG_OPTS
48+
49+
M cime_config/buildnml
50+
- copy TUV-X input data to run directory only if "-tuvx" is included in CAM_CONFIG_OPTS
51+
52+
M cime_config/config_component.xml
53+
- remove tuvx and yaml-cpp libs from default setting of CAM_LINKED_LIBS
54+
-- buildlib will add these only only if cam is configured for tuvx
155

56+
M cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/shell_commands
57+
M cime_config/testdefs/testmods_dirs/cam/outfrq9s_tuvx_waccm_ma_mam5/shell_commands
58+
M cime_config/testdefs/testmods_dirs/cam/outfrq9s_waccm_ma_mam4/shell_commands
59+
-- append "-tuvx" to CAM_CONFIG_OPTS
60+
61+
M src/chemistry/mozart/mo_tuvx.F90
62+
- use ifdefs to stub out the module for cases where TUV-X lib is not available
63+
64+
If there were any failures reported from running test_driver.sh on any test
65+
platform, and checkin with these failures has been OK'd by the gatekeeper,
66+
then copy the lines from the td.*.status files for the failed tests to the
67+
appropriate machine below. All failed tests must be justified.
68+
69+
derecho/intel/aux_cam: All PASS
70+
71+
derecho/nvhpc/aux_cam: All PASS
72+
73+
izumi/nag/aux_cam:
74+
FAIL ERC_D_Ln9.f10_f10_mt232.FHIST_C5.izumi_nag.cam-outfrq3s_subcol COMPARE_base_rest
75+
- pre-existing failure -- see https://github.com/ESCOMP/CAM/issues/1514
76+
77+
izumi/gnu/aux_cam: All PASS
78+
79+
Summarize any changes to answers: bit-for-bit
80+
81+
===============================================================
282
===============================================================
383

484
Tag name: cam6_4_181

0 commit comments

Comments
 (0)