diff --git a/branch/rljacob/docs/update-testing/html/.buildinfo b/branch/rljacob/docs/update-testing/html/.buildinfo new file mode 100644 index 00000000000..988fcd3d192 --- /dev/null +++ b/branch/rljacob/docs/update-testing/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 59a70d6cd69f70c7bf67975447c10eae +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/branch/rljacob/docs/update-testing/html/.nojekyll b/branch/rljacob/docs/update-testing/html/.nojekyll new file mode 100644 index 00000000000..e69de29bb2d diff --git a/branch/rljacob/docs/update-testing/html/CIME_api/CIME.BuildTools.html b/branch/rljacob/docs/update-testing/html/CIME_api/CIME.BuildTools.html new file mode 100644 index 00000000000..bae978f8b6f --- /dev/null +++ b/branch/rljacob/docs/update-testing/html/CIME_api/CIME.BuildTools.html @@ -0,0 +1,225 @@ + + +
+ + + +This module contains functions for working with user_nl files in system tests.
+Append the string(s) given by ‘contents’ to the end of each user_nl file for +the given component (there may be multiple such user_nl files in the case of +a multi-instance test).
+Also puts new lines before and after the appended text - so ‘contents’ +does not need to contain a trailing new line (but it’s also okay if it +does).
+caseroot (str): Full path to the case directory
+determine which user_nl files are appended to. For example, for +component=’clm’, this function will operate on all user_nl files +matching the pattern ‘user_nl_clm*’. (We do a wildcard match to +handle multi-instance tests.)
+file. If list-like, each item will be appended on its own line.
+DummyCase
+TestParamGen
+TestParamGenXmlConstructor
TestParamGenXmlConstructor.test_default_var()
TestParamGenXmlConstructor.test_duplicate_entry_error()
TestParamGenXmlConstructor.test_mixed_guard()
TestParamGenXmlConstructor.test_mixed_guard_first()
TestParamGenXmlConstructor.test_no_match()
TestParamGenXmlConstructor.test_single_key_val_guard()
TestParamGenYamlConstructor
+TestUserNLCopier
TestUserNLCopier.assertFileContentsEqual()
TestUserNLCopier.setUp()
TestUserNLCopier.tearDown()
TestUserNLCopier.test_append()
TestUserNLCopier.test_append_list()
TestUserNLCopier.test_append_multiple_files()
TestUserNLCopier.test_append_without_files_raises_exception()
TestUserNLCopier.write_user_nl_file()
This module contains a fake implementation of the Case class that can be used +for testing the tests.
+Bases: object
Create and return a copy of self, but with CASE and CASEBASEID set to newcasename, +CASEROOT set to newcaseroot, and RUNDIR set appropriately.
+newcasename (str): new value for CASE +newcaseroot (str): new value for CASEROOT
+Create a clone of the current case. Also creates the CASEROOT directory +for the clone case (given by newcase).
+already exist; it will be created
+keepexe (bool, optional): Ignored +mach_dir (str, optional): Ignored +project (str, optional): Ignored +cime_output_root (str, optional): New CIME_OUTPUT_ROOT for the clone +exeroot (str, optional): New EXEROOT for the clone +rundir (str, optional): New RUNDIR for the clone
+Returns the clone case object
+Get the value of the given item
+Returns None if item isn’t set for this case
+item (str): variable of interest
+Assumes CASEROOT is already set; sets an appropriate EXEROOT +(nested inside CASEROOT)
+This module contains unit tests of CaseFake
+ + +This module tests some functionality of CIME.ParamGen.paramgen’s ParamGen class
+Bases: object
A dummy Case class that mimics CIME class objects’ get_value method.
+ + +Bases: TestCase
Tests some basic functionality of the +CIME.ParamGen.paramgen’s ParamGen class
+Tests the reduce method of ParamGen expandable vars in guards.
+Tests the default behavior of returning the last match and the optional behavior of returning the +first match.
+Tests the reduce method on data with outer guards enclosing parameter definitions.
+Bases: TestCase
A unit test class for testing ParamGen’s xml constructor.
+Test to check if default val is assigned when all guards eval to False
+Test to make sure duplicate ids raise the correct error +when the “no_duplicates” flag is True.
+Tests multiple key=value guards mixed with explicit (flexible) guards.
+Tests multiple key=value guards mixed with explicit (flexible) guards +with match=first option.
+Bases: TestCase
A unit test class for testing ParamGen’s yaml constructor.
+ + + + +Bases: TestCase
Asserts that the contents of the file given by ‘filepath’ are equal to +the string given by ‘expected’. ‘msg’ gives an optional message to be +printed if the assertion fails.
+Write contents to a user_nl file in the case directory. Returns the +basename (i.e., not the full path) of the file that is created.
+For a component foo, with the default suffix of ‘’, the file name will +be user_nl_foo
+If the suffix is ‘_0001’, the file name will be user_nl_foo_0001
+advanced-py-prof is a script in CIMEROOT/CIME/Tools.
+$ ./advanced-py-prof --help
+Traceback (most recent call last):
+ File "<frozen runpy>", line 198, in _run_module_as_main
+ File "<frozen runpy>", line 88, in _run_code
+ File "/opt/hostedtoolcache/Python/3.12.3/x64/lib/python3.12/cProfile.py", line 195, in <module>
+ main()
+ File "/opt/hostedtoolcache/Python/3.12.3/x64/lib/python3.12/cProfile.py", line 172, in main
+ with io.open_code(progname) as fp:
+ ^^^^^^^^^^^^^^^^^^^^^^
+FileNotFoundError: [Errno 2] No such file or directory: 'basename'
+
archive_metadata is a script in CIMEROOT/CIME/Tools.
+$ ./archive_metadata --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./archive_metadata", line 27, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
bld_diff is a script in CIMEROOT/CIME/Tools.
+$ ./bld_diff --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./bld_diff", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
bless_test_results is a script in CIMEROOT/CIME/Tools.
+$ ./bless_test_results --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./bless_test_results", line 11, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case.build is a script in CIMEROOT/CIME/Tools.
+$ ./case.build --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case.build", line 45, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case.cmpgen_namelists is a script in CIMEROOT/CIME/Tools.
+$ ./case.cmpgen_namelists --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case.cmpgen_namelists", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case.qstatus is a script in CIMEROOT/CIME/Tools.
+$ ./case.qstatus --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case.qstatus", line 10, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case.setup is a script in CIMEROOT/CIME/Tools.
+$ ./case.setup --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case.setup", line 19, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case.submit is a script in CIMEROOT/CIME/Tools.
+$ ./case.submit --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case.submit", line 19, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
case_diff is a script in CIMEROOT/CIME/Tools.
+$ ./case_diff --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./case_diff", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
check_case is a script in CIMEROOT/CIME/Tools.
+$ ./check_case --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./check_case", line 20, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
check_input_data is a script in CIMEROOT/CIME/Tools.
+$ ./check_input_data --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./check_input_data", line 21, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
check_lockedfiles is a script in CIMEROOT/CIME/Tools.
+$ ./check_lockedfiles --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./check_lockedfiles", line 6, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
cime_bisect is a script in CIMEROOT/CIME/Tools.
+$ ./cime_bisect --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./cime_bisect", line 12, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
code_checker is a script in CIMEROOT/CIME/Tools.
+$ ./code_checker --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./code_checker", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
compare_namelists is a script in CIMEROOT/CIME/Tools.
+$ ./compare_namelists --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./compare_namelists", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
compare_test_results is a script in CIMEROOT/CIME/Tools.
+$ ./compare_test_results --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./compare_test_results", line 24, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
component_compare_baseline is a script in CIMEROOT/CIME/Tools.
+$ ./component_compare_baseline --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./component_compare_baseline", line 7, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
component_compare_copy is a script in CIMEROOT/CIME/Tools.
+$ ./component_compare_copy --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./component_compare_copy", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
component_compare_test is a script in CIMEROOT/CIME/Tools.
+$ ./component_compare_test --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./component_compare_test", line 7, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
component_generate_baseline is a script in CIMEROOT/CIME/Tools.
+$ ./component_generate_baseline --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./component_generate_baseline", line 7, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
concat_daily_hist.csh is a script in CIMEROOT/CIME/Tools.
+create_clone is a script in CIMEROOT/scripts.
+$ ./create_clone --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/scripts/./create_clone", line 15, in <module>
+ from CIME.scripts.create_clone import _main_func
+ File "/home/runner/work/cime/cime/CIME/scripts/create_clone.py", line 3, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
create_newcase is a script in CIMEROOT/scripts.
+$ ./create_newcase --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/scripts/./create_newcase", line 15, in <module>
+ from CIME.scripts.create_newcase import _main_func
+ File "/home/runner/work/cime/cime/CIME/scripts/create_newcase.py", line 9, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
create_test is a script in CIMEROOT/scripts.
+$ ./create_test --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/scripts/./create_test", line 15, in <module>
+ from CIME.scripts.create_test import _main_func
+ File "/home/runner/work/cime/cime/CIME/scripts/create_test.py", line 29, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
cs.status is a script in CIMEROOT/CIME/Tools.
+$ ./cs.status --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./cs.status", line 11, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
e3sm_check_env is a script in CIMEROOT/CIME/Tools.
+$ ./e3sm_check_env --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./e3sm_check_env", line 9, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
generate_cylc_workflow.py is a script in CIMEROOT/CIME/Tools.
+$ ./generate_cylc_workflow.py --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./generate_cylc_workflow.py", line 11, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
getTiming is a script in CIMEROOT/CIME/Tools.
+$ ./getTiming --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./getTiming", line 6, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
get_case_env is a script in CIMEROOT/CIME/Tools.
+$ ./get_case_env --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./get_case_env", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
get_standard_makefile_args is a script in CIMEROOT/CIME/Tools.
+$ ./get_standard_makefile_args --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./get_standard_makefile_args", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
CIME includes a number of user scripts. Some of these scripts are copied into +the CASEROOT as part of create_newcase, create_test, create_clone, +and case.setup.
+jenkins_generic_job is a script in CIMEROOT/CIME/Tools.
+$ ./jenkins_generic_job --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./jenkins_generic_job", line 10, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
list_e3sm_tests is a script in CIMEROOT/CIME/Tools.
+$ ./list_e3sm_tests --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./list_e3sm_tests", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
mkDepends is a script in CIMEROOT/CIME/Tools.
+$ ./mkDepends --help
+SYNOPSIS
+ mkDepends [-p [-Dmacro[=val]] [-Umacro] [-Idir]] [-d depfile]
+ [-m mangle_scheme] [-t dir] [-w] Filepath Srcfiles
+OPTIONS
+ -p
+ Preprocess files (suffix .F and .F90) before searching
+ for module dependencies. Default CPP preprocessor: cpp.
+ Set env variables CPP and/or CPPFLAGS to override.
+ -D macro[=val]
+ Define the CPP macro with val as its value.
+ Ignored when -p option is not active.
+ -U macro
+ Undefine the CPP macro.
+ Ignored when -p option is not active.
+ -I dir
+ Add dir to the include path for CPP.
+ Ignored when -p option is not active.
+ -d depfile
+ Additional file to be added to every .o dependence.
+ -m mangle_scheme
+ Method of mangling Fortran module names into .mod filenames.
+ Allowed values are:
+ lower - Filename is module_name.mod
+ upper - Filename is MODULE_NAME.MOD
+ The default is -m lower.
+ -t dir
+ Target directory. If this option is set the .o files that are
+ targets in the dependency rules have the form dir/file.o.
+ -w Print warnings to STDERR about files or dependencies not found.
+ARGUMENTS
+ Filepath is the name of a file containing the directories (one per
+ line) to be searched for dependencies. Srcfiles is the name of a
+ file containing the names of files (one per line) for which
+ dependencies will be generated.
+
mkSrcfiles is a script in CIMEROOT/CIME/Tools.
+$ ./mkSrcfiles --help
+SYNOPSIS
+ mkSrcfiles
+DESCRIPTION
+ The mkSrcfiles utility assumes the existence of an input file
+ ./Filepath, and writes an output file ./Srcfiles that contains
+ the names of all the files that match the patterns *.F90, *.F,
+ and *.c in all the directories from ./Filepath plus ./. The
+ files are listed one per line.
+
mvsource is a script in CIMEROOT/CIME/Tools.
+$ ./mvsource --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./mvsource", line 8, in <module>
+ cimeroot = sys.argv[2]
+ ~~~~~~~~^^^
+IndexError: list index out of range
+
normalize_cases is a script in CIMEROOT/CIME/Tools.
+$ ./normalize_cases --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./normalize_cases", line 11, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
pelayout is a script in CIMEROOT/CIME/Tools.
+$ ./pelayout --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./pelayout", line 41, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
preview_namelists is a script in CIMEROOT/CIME/Tools.
+$ ./preview_namelists --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./preview_namelists", line 18, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
preview_run is a script in CIMEROOT/CIME/Tools.
+$ ./preview_run --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./preview_run", line 19, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
query_config is a script in CIMEROOT/scripts.
+$ ./query_config --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/scripts/./query_config", line 15, in <module>
+ from CIME.scripts.query_config import _main_func
+ File "/home/runner/work/cime/cime/CIME/scripts/query_config.py", line 9, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
query_testlists is a script in CIMEROOT/scripts.
+$ ./query_testlists --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/scripts/./query_testlists", line 15, in <module>
+ from CIME.scripts.query_testlists import _main_func
+ File "/home/runner/work/cime/cime/CIME/scripts/query_testlists.py", line 17, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
save_provenance is a script in CIMEROOT/CIME/Tools.
+$ ./save_provenance --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./save_provenance", line 7, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
simple-py-prof is a script in CIMEROOT/CIME/Tools.
+$ ./simple-py-prof --help
+Usage: cProfile.py [-o output_file_path] [-s sort] [-m module | scriptfile] [arg] ...
+
+Options:
+ -h, --help show this help message and exit
+ -o OUTFILE, --outfile=OUTFILE
+ Save stats to <outfile>
+ -s SORT, --sort=SORT Sort order when printing to stdout, based on
+ pstats.Stats class
+ -m Profile a library module
+
simple_compare is a script in CIMEROOT/CIME/Tools.
+$ ./simple_compare --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./simple_compare", line 8, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
testreporter.py is a script in CIMEROOT/CIME/Tools.
+$ ./testreporter.py --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./testreporter.py", line 11, in <module>
+ from CIME.Tools.standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
wait_for_tests is a script in CIMEROOT/CIME/Tools.
+$ ./wait_for_tests --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./wait_for_tests", line 11, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
xmlchange is a script in CIMEROOT/CIME/Tools.
+$ ./xmlchange --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./xmlchange", line 49, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
xmlquery is a script in CIMEROOT/CIME/Tools.
+$ ./xmlquery --help
+Traceback (most recent call last):
+ File "/home/runner/work/cime/cime/CIME/Tools/./xmlquery", line 100, in <module>
+ from standard_script_setup import *
+ File "/home/runner/work/cime/cime/CIME/Tools/standard_script_setup.py", line 42, in <module>
+ import CIME.utils
+ File "/home/runner/work/cime/cime/CIME/utils.py", line 15, in <module>
+ from distutils import file_util
+ModuleNotFoundError: No module named 'distutils'
+
xmltestentry is a script in CIMEROOT/CIME/Tools.
+$ ./xmltestentry --help
+Unknown option: help
+Could not open file! at ./xmltestentry line 23.
+
+"""
+This module contains functions for working with user_nl files in system tests.
+"""
+
+import os
+import glob
+
+
+
+[docs]
+def append_to_user_nl_files(caseroot, component, contents):
+ """
+ Append the string(s) given by 'contents' to the end of each user_nl file for
+ the given component (there may be multiple such user_nl files in the case of
+ a multi-instance test).
+
+ Also puts new lines before and after the appended text - so 'contents'
+ does not need to contain a trailing new line (but it's also okay if it
+ does).
+
+ Args:
+ caseroot (str): Full path to the case directory
+
+ component (str): Name of component (e.g., 'clm'). This is used to
+ determine which user_nl files are appended to. For example, for
+ component='clm', this function will operate on all user_nl files
+ matching the pattern 'user_nl_clm*'. (We do a wildcard match to
+ handle multi-instance tests.)
+
+ contents (str or list-like): Contents to append to the end of each user_nl
+ file. If list-like, each item will be appended on its own line.
+ """
+
+ if isinstance(contents, str):
+ contents = [contents]
+
+ files = _get_list_of_user_nl_files(caseroot, component)
+
+ if len(files) == 0:
+ raise RuntimeError("No user_nl files found for component " + component)
+
+ for one_file in files:
+ with open(one_file, "a") as user_nl_file:
+ user_nl_file.write("\n")
+ for c in contents:
+ user_nl_file.write(c + "\n")
+
+
+
+def _get_list_of_user_nl_files(path, component):
+ """Get a list of all user_nl files in the current path for the component
+ of interest. For a component 'foo', we match all files of the form
+ user_nl_foo* - with a wildcard match at the end in order to match files
+ in a multi-instance case.
+
+ The list of returned files gives their full path.
+ """
+
+ file_pattern = "user_nl_" + component + "*"
+ file_list = glob.glob(os.path.join(path, file_pattern))
+
+ return file_list
+
+"""
+This module contains a fake implementation of the Case class that can be used
+for testing the tests.
+"""
+
+import os
+from copy import deepcopy
+
+
+
+[docs]
+class CaseFake(object):
+ def __init__(self, case_root, create_case_root=True):
+ """
+ Initialize a new case object for the given case_root directory.
+
+ Args:
+ case_root (str): path to CASEROOT
+ create_case_root (bool): If True, creates the directory given by case_root
+ """
+ self.vars = dict()
+ if create_case_root:
+ os.makedirs(case_root)
+ self.set_value("CASEROOT", case_root)
+ casename = os.path.basename(case_root)
+ # Typically, CIME_OUTPUT_ROOT is independent of the case. Here,
+ # we nest it under CASEROOT so that (1) tests don't interfere
+ # with each other; (2) a cleanup that removes CASEROOT will also
+ # remove CIME_OUTPUT_ROOT.
+ self.set_value("CIME_OUTPUT_ROOT", os.path.join(case_root, "CIME_OUTPUT_ROOT"))
+ self.set_value("CASE", casename)
+ self.set_value("CASEBASEID", casename)
+ self.set_value("RUN_TYPE", "startup")
+ self.set_exeroot()
+ self.set_rundir()
+
+
+
+
+
+[docs]
+ def get_value(self, item):
+ """
+ Get the value of the given item
+
+ Returns None if item isn't set for this case
+
+ Args:
+ item (str): variable of interest
+ """
+ return self.vars.get(item)
+
+
+
+[docs]
+ def set_value(self, item, value):
+ """
+ Set the value of the given item to the given value
+
+ Args:
+ item (str): variable of interest
+ value (any type): new value for item
+ """
+ self.vars[item] = value
+
+
+
+[docs]
+ def copy(self, newcasename, newcaseroot):
+ """
+ Create and return a copy of self, but with CASE and CASEBASEID set to newcasename,
+ CASEROOT set to newcaseroot, and RUNDIR set appropriately.
+
+ Args:
+ newcasename (str): new value for CASE
+ newcaseroot (str): new value for CASEROOT
+ """
+ newcase = deepcopy(self)
+ newcase.set_value("CASE", newcasename)
+ newcase.set_value("CASEBASEID", newcasename)
+ newcase.set_value("CASEROOT", newcaseroot)
+ newcase.set_exeroot()
+ newcase.set_rundir()
+
+ return newcase
+
+
+
+[docs]
+ def create_clone(
+ self,
+ newcase,
+ keepexe=False,
+ mach_dir=None,
+ project=None,
+ cime_output_root=None,
+ exeroot=None,
+ rundir=None,
+ ):
+ # Need to disable unused-argument checking: keepexe is needed to match
+ # the interface of Case, but is not used in this fake implementation
+ #
+ # pylint: disable=unused-argument
+ """
+ Create a clone of the current case. Also creates the CASEROOT directory
+ for the clone case (given by newcase).
+
+ Args:
+ newcase (str): full path to the new case. This directory should not
+ already exist; it will be created
+ keepexe (bool, optional): Ignored
+ mach_dir (str, optional): Ignored
+ project (str, optional): Ignored
+ cime_output_root (str, optional): New CIME_OUTPUT_ROOT for the clone
+ exeroot (str, optional): New EXEROOT for the clone
+ rundir (str, optional): New RUNDIR for the clone
+
+ Returns the clone case object
+ """
+ newcaseroot = os.path.abspath(newcase)
+ newcasename = os.path.basename(newcase)
+ os.makedirs(newcaseroot)
+ clone = self.copy(newcasename=newcasename, newcaseroot=newcaseroot)
+ if cime_output_root is not None:
+ clone.set_value("CIME_OUTPUT_ROOT", cime_output_root)
+ if exeroot is not None:
+ clone.set_value("EXEROOT", exeroot)
+ if rundir is not None:
+ clone.set_value("RUNDIR", rundir)
+
+ return clone
+
+
+
+
+
+
+[docs]
+ def make_rundir(self):
+ """
+ Make directory given by RUNDIR
+ """
+ os.makedirs(self.get_value("RUNDIR"))
+
+
+
+[docs]
+ def set_exeroot(self):
+ """
+ Assumes CASEROOT is already set; sets an appropriate EXEROOT
+ (nested inside CASEROOT)
+ """
+ self.set_value("EXEROOT", os.path.join(self.get_value("CASEROOT"), "bld"))
+
+
+
+[docs]
+ def set_rundir(self):
+ """
+ Assumes CASEROOT is already set; sets an appropriate RUNDIR (nested
+ inside CASEROOT)
+ """
+ self.set_value("RUNDIR", os.path.join(self.get_value("CASEROOT"), "run"))
+
+
+
+
+
+
+
+
+ def __enter__(self):
+ pass
+
+ def __exit__(self, *_):
+ pass
+
+
+#!/usr/bin/env python3
+
+"""
+This module contains unit tests of CaseFake
+"""
+
+import unittest
+import tempfile
+import os
+import shutil
+
+from CIME.tests.case_fake import CaseFake
+
+
+
+[docs]
+class TestCaseFake(unittest.TestCase):
+
+
+
+
+
+
+
+[docs]
+ def test_create_clone(self):
+ # Setup
+ old_caseroot = os.path.join(self.tempdir, "oldcase")
+ oldcase = CaseFake(old_caseroot)
+ oldcase.set_value("foo", "bar")
+
+ # Exercise
+ new_caseroot = os.path.join(self.tempdir, "newcase")
+ clone = oldcase.create_clone(new_caseroot)
+
+ # Verify
+ self.assertEqual("bar", clone.get_value("foo"))
+ self.assertEqual("newcase", clone.get_value("CASE"))
+ self.assertEqual("newcase", clone.get_value("CASEBASEID"))
+ self.assertEqual(new_caseroot, clone.get_value("CASEROOT"))
+ self.assertEqual(os.path.join(new_caseroot, "run"), clone.get_value("RUNDIR"))
+
+
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+#!/usr/bin/env python3
+
+"""
+This module tests *some* functionality of CIME.ParamGen.paramgen's ParamGen class
+"""
+
+# Ignore privacy concerns for unit tests, so that unit tests can access
+# protected members of the system under test
+#
+# pylint:disable=protected-access
+
+# Also ignore too-long lines, since these are common in unit tests
+#
+# pylint:disable=line-too-long
+
+import unittest
+import tempfile
+from CIME.ParamGen.paramgen import ParamGen
+
+###############
+# Example inputs
+###############
+
+_MOM_INPUT_YAML = """
+Global:
+ INPUTDIR:
+ value: ${DIN_LOC_ROOT}/ocn/mom/${OCN_GRID}
+ RESTORE_SALINITY:
+ value:
+ $OCN_GRID == "tx0.66v1" and $COMP_ATM == "datm": True # for C and G compsets on tx0.66v1
+ else: False
+ INIT_LAYERS_FROM_Z_FILE:
+ value:
+ $OCN_GRID == "gx1v6": True
+ $OCN_GRID == "tx0.66v1": True
+ $OCN_GRID == "tx0.25v1": True
+ TEMP_SALT_Z_INIT_FILE:
+ value:
+ $OCN_GRID == "gx1v6": "WOA05_pottemp_salt.nc"
+ $OCN_GRID == "tx0.66v1": "woa18_04_initial_conditions.nc"
+ $OCN_GRID == "tx0.25v1": "MOM6_IC_TS.nc"
+"""
+
+_MOM_INPUT_DATA_LIST_YAML = """
+mom.input_data_list:
+ ocean_hgrid:
+ $OCN_GRID == "gx1v6": "${INPUTDIR}/ocean_hgrid.nc"
+ $OCN_GRID == "tx0.66v1": "${INPUTDIR}/ocean_hgrid_180829.nc"
+ $OCN_GRID == "tx0.25v1": "${INPUTDIR}/ocean_hgrid.nc"
+ tempsalt:
+ $OCN_GRID in ["gx1v6", "tx0.66v1", "tx0.25v1"]:
+ $INIT_LAYERS_FROM_Z_FILE == "True":
+ "${INPUTDIR}/${TEMP_SALT_Z_INIT_FILE}"
+"""
+
+_MY_TEMPLATE_XML = """<?xml version="1.0"?>
+
+<entry_id_pg version="0.1">
+
+ <entry id="foo">
+ <type>string</type>
+ <group>test_nml</group>
+ <desc>a dummy parameter for testing single key=value guards</desc>
+ <values>
+ <value>alpha</value>
+ <value cice_mode="thermo_only">beta</value>
+ <value cice_mode="prescribed">gamma</value>
+ </values>
+ </entry>
+
+ <entry id="bar">
+ <type>string</type>
+ <group>test_nml</group>
+ <desc>another dummy parameter for multiple key=value guards mixed with explicit (flexible) guards</desc>
+ <values>
+ <value some_int="2" some_bool="True" some_float="3.1415">delta</value>
+ <value guard='$ICE_GRID .startswith("gx1v")'>epsilon</value>
+ </values>
+ </entry>
+
+ <entry id="baz">
+ <type>string</type>
+ <group>test_nml</group>
+ <desc>parameter to test the case where there is no match</desc>
+ <values>
+ <value some_int="-9999">zeta</value>
+ <value guard='not $ICE_GRID .startswith("gx1v")'>eta</value>
+ </values>
+ </entry>
+
+ </entry_id_pg>
+"""
+
+_DUPLICATE_IDS_XML = """<?xml version="1.0"?>
+
+<entry_id_pg version="0.1">
+
+ <entry id="foo">
+ <type>string</type>
+ <group>test_nml</group>
+ <desc>a dummy parameter for testing single key=value guards</desc>
+ <values>
+ <value>alpha</value>
+ <value cice_mode="thermo_only">beta</value>
+ <value cice_mode="prescribed">gamma</value>
+ </values>
+ </entry>
+
+ <entry id="foo">
+ <type>string</type>
+ <group>test_nml</group>
+ <desc>another dummy parameter for multiple key=value guards mixed with explicit (flexible) guards</desc>
+ <values>
+ <value some_int="2" some_bool="True" some_float="3.1415">delta</value>
+ <value guard='$ICE_GRID .startswith("gx1v")'>epsilon</value>
+ </values>
+ </entry>
+
+ </entry_id_pg>
+"""
+
+############################
+# Dummy functions and classes
+############################
+
+
+
+[docs]
+class DummyCase:
+ """A dummy Case class that mimics CIME class objects' get_value method."""
+
+
+[docs]
+ def get_value(self, varname):
+ d = {
+ "DIN_LOC_ROOT": "/foo/inputdata",
+ "OCN_GRID": "tx0.66v1",
+ "COMP_ATM": "datm",
+ }
+ return d[varname] if varname in d else None
+
+
+
+
+case = DummyCase()
+
+#####
+
+
+def _expand_func_demo(varname):
+ return {
+ "ICE_GRID": "gx1v6",
+ "DIN_LOC_ROOT": "/glade/p/cesmdata/cseg/inputdata",
+ "cice_mode": "thermo_only",
+ "some_bool": "True",
+ "some_int": 2,
+ "some_float": "3.1415",
+ }[varname]
+
+
+################
+# Unitest classes
+################
+
+
+
+[docs]
+class TestParamGen(unittest.TestCase):
+ """
+ Tests some basic functionality of the
+ CIME.ParamGen.paramgen's ParamGen class
+ """
+
+
+[docs]
+ def test_init_data(self):
+ """Tests the ParamGen initializer with and without an initial data."""
+ # empty
+ _ = ParamGen({})
+ # with data
+ data_dict = {"a": 1, "b": 2}
+ _ = ParamGen(data_dict)
+
+
+
+[docs]
+ def test_reduce(self):
+ """Tests the reduce method of ParamGen on data with explicit guards (True or False)."""
+ data_dict = {"False": 1, "True": 2}
+ obj = ParamGen(data_dict)
+ obj.reduce()
+ self.assertEqual(obj.data, 2)
+
+
+
+[docs]
+ def test_nested_reduce(self):
+ """Tests the reduce method of ParamGen on data with nested guards."""
+ data_dict = {"False": 1, "True": {"2>3": 0, "2<3": 2}}
+ obj = ParamGen(data_dict)
+ obj.reduce()
+ self.assertEqual(obj.data, 2)
+
+
+
+[docs]
+ def test_outer_guards(self):
+ """Tests the reduce method on data with outer guards enclosing parameter definitions."""
+ data_dict = {
+ "False": {"param": "foo"},
+ "True": {"param": "bar"},
+ }
+ obj = ParamGen(data_dict)
+ obj.reduce()
+ self.assertEqual(obj.data, {"param": "bar"})
+
+
+
+[docs]
+ def test_match(self):
+ """Tests the default behavior of returning the last match and the optional behavior of returning the
+ first match."""
+
+ data_dict = {
+ "1<2": "foo",
+ "2<3": "bar",
+ "3<4": "baz",
+ }
+
+ obj = ParamGen(data_dict) # by default, match='last'
+ obj.reduce()
+ self.assertEqual(obj.data, "baz")
+
+ obj = ParamGen(data_dict, match="first")
+ obj.reduce()
+ self.assertEqual(obj.data, "foo")
+
+
+
+[docs]
+ def test_undefined_var(self):
+ """Tests the reduce method of ParamGen on nested guards where an undefined expandable var is specified
+ below a guard that evaluates to False. The undefined var should not lead to an error since the enclosing
+ guard evaluates to false."""
+
+ # define an expansion function, i.e., a mapping for expandable var names to their values
+ test_map = {"alpha": 1, "beta": False}
+ expand_func = lambda var: test_map[var]
+
+ # define a data dict
+ data_dict = {"param": {"$alpha >= 1": "foo", "${beta}": {"${zeta}": "bar"}}}
+
+ # Instantiate a ParamGen object and reduce its data to obtain the final parameter set
+ obj = ParamGen(data_dict)
+ obj.reduce(expand_func)
+ self.assertEqual(obj.data, {"param": "foo"})
+
+
+
+[docs]
+ def test_expandable_vars(self):
+ """Tests the reduce method of ParamGen expandable vars in guards."""
+
+ # define an expansion function, i.e., a mapping for expandable var names to their values
+ test_map = {"alpha": 1, "beta": False, "gamma": "xyz"}
+ expand_func = lambda var: test_map[var]
+
+ # define a data dict
+ data_dict = {
+ "param": {"$alpha > 1": "foo", "${beta}": "bar", '"x" in $gamma': "baz"}
+ }
+
+ # Instantiate a ParamGen object and reduce its data to obtain the final parameter set
+ obj = ParamGen(data_dict)
+ obj.reduce(expand_func)
+ self.assertEqual(obj.data, {"param": "baz"})
+
+
+
+[docs]
+ def test_formula_expansion(self):
+ """Tests the formula expansion feature of ParamGen."""
+
+ # define an expansion function, i.e., a mapping for expandable var names to their values
+ test_map = {"alpha": 3}
+ expand_func = lambda var: test_map[var]
+
+ # define a data dict
+ data_dict = {"x": "= $alpha **2", "y": "= [i for i in range(3)]"}
+
+ # Instantiate a ParamGen object and reduce its data to obtain the final parameter set
+ obj = ParamGen(data_dict)
+ obj.reduce(expand_func)
+ self.assertEqual(obj.data["x"], 9)
+ self.assertEqual(obj.data["y"], [0, 1, 2])
+
+
+
+
+#####
+
+
+
+[docs]
+class TestParamGenYamlConstructor(unittest.TestCase):
+ """A unit test class for testing ParamGen's yaml constructor."""
+
+
+[docs]
+ def test_mom_input(self):
+ """Test MOM_input file generation via a subset of original MOM_input.yaml"""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MOM_INPUT_YAML.encode())
+ temp.flush()
+
+ # Open YAML file using ParamGen:
+ mom_input = ParamGen.from_yaml(temp.name)
+
+ # Define a local ParamGen reducing function:
+ def input_data_list_expand_func(varname):
+ val = case.get_value(varname)
+ if val == None:
+ val = str(mom_input.data["Global"][varname]["value"]).strip()
+ if val == None:
+ raise RuntimeError("Cannot determine the value of variable: " + varname)
+ return val
+
+ # Reduce ParamGen entries:
+ mom_input.reduce(input_data_list_expand_func)
+
+ # Check output:
+ self.assertEqual(
+ mom_input.data,
+ {
+ "Global": {
+ "INPUTDIR": {"value": "/foo/inputdata/ocn/mom/tx0.66v1"},
+ "RESTORE_SALINITY": {"value": True},
+ "INIT_LAYERS_FROM_Z_FILE": {"value": True},
+ "TEMP_SALT_Z_INIT_FILE": {
+ "value": "woa18_04_initial_conditions.nc"
+ },
+ }
+ },
+ )
+
+
+
+[docs]
+ def test_input_data_list(self):
+ """Test mom.input_data_list file generation via a subset of original input_data_list.yaml"""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MOM_INPUT_YAML.encode())
+ temp.flush()
+
+ # Open YAML file using ParamGen:
+ mom_input = ParamGen.from_yaml(temp.name)
+
+ # Define a local ParamGen reducing function:
+ def input_data_list_expand_func(varname):
+ val = case.get_value(varname)
+ if val == None:
+ val = str(mom_input.data["Global"][varname]["value"]).strip()
+ if val == None:
+ raise RuntimeError("Cannot determine the value of variable: " + varname)
+ return val
+
+ # Reduce ParamGen entries:
+ mom_input.reduce(input_data_list_expand_func)
+
+ # Create a second temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp2:
+ temp2.write(_MOM_INPUT_DATA_LIST_YAML.encode())
+ temp2.flush()
+
+ # Open second YAML file using ParamGen:
+ input_data_list = ParamGen.from_yaml(temp2.name)
+
+ # Reduce ParamGen entries:
+ input_data_list.reduce(input_data_list_expand_func)
+
+ # Check output:
+ self.assertEqual(
+ input_data_list.data,
+ {
+ "mom.input_data_list": {
+ "ocean_hgrid": "/foo/inputdata/ocn/mom/tx0.66v1/ocean_hgrid_180829.nc",
+ "tempsalt": "/foo/inputdata/ocn/mom/tx0.66v1/woa18_04_initial_conditions.nc",
+ }
+ },
+ )
+
+
+
+
+#####
+
+
+
+[docs]
+class TestParamGenXmlConstructor(unittest.TestCase):
+ """A unit test class for testing ParamGen's xml constructor."""
+
+
+[docs]
+ def test_single_key_val_guard(self):
+ """Test xml entry values with single key=value guards"""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MY_TEMPLATE_XML.encode())
+ temp.flush()
+
+ # Open XML file using ParamGen:
+ pg = ParamGen.from_xml_nml(temp.name)
+
+ # Reduce ParamGen entries:
+ pg.reduce(_expand_func_demo)
+
+ # Check output:
+ self.assertEqual(pg.data["test_nml"]["foo"]["values"], "beta")
+
+
+
+[docs]
+ def test_mixed_guard(self):
+ """Tests multiple key=value guards mixed with explicit (flexible) guards."""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MY_TEMPLATE_XML.encode())
+ temp.flush()
+
+ # Open XML file using ParamGen:
+ pg = ParamGen.from_xml_nml(temp.name)
+
+ # Reduce ParamGen entries:
+ pg.reduce(_expand_func_demo)
+
+ # Check output:
+ self.assertEqual(pg.data["test_nml"]["bar"]["values"], "epsilon")
+
+
+
+[docs]
+ def test_mixed_guard_first(self):
+ """Tests multiple key=value guards mixed with explicit (flexible) guards
+ with match=first option."""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MY_TEMPLATE_XML.encode())
+ temp.flush()
+
+ # Open XML file using ParamGen:
+ pg = ParamGen.from_xml_nml(temp.name, match="first")
+
+ # Reduce ParamGen entries:
+ pg.reduce(_expand_func_demo)
+
+ # Check output:
+ self.assertEqual(pg.data["test_nml"]["bar"]["values"], "delta")
+
+
+
+[docs]
+ def test_no_match(self):
+ """Tests an xml entry with no match, i.e., no guards evaluating to True."""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MY_TEMPLATE_XML.encode())
+ temp.flush()
+
+ # Open XML file using ParamGen:
+ pg = ParamGen.from_xml_nml(temp.name)
+
+ # Reduce ParamGen entries:
+ pg.reduce(_expand_func_demo)
+
+ # Check output:
+ self.assertEqual(pg.data["test_nml"]["baz"]["values"], None)
+
+
+
+[docs]
+ def test_default_var(self):
+ """Test to check if default val is assigned when all guards eval to False"""
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_MY_TEMPLATE_XML.encode())
+ temp.flush()
+
+ # Open XML file using ParamGen:
+ pg = ParamGen.from_xml_nml(temp.name)
+
+ # Reduce ParamGen entries:
+ pg.reduce(lambda varname: "_")
+
+ # Check output:
+ self.assertEqual(pg.data["test_nml"]["foo"]["values"], "alpha")
+
+
+
+[docs]
+ def test_duplicate_entry_error(self):
+ """
+ Test to make sure duplicate ids raise the correct error
+ when the "no_duplicates" flag is True.
+ """
+ with self.assertRaises(ValueError) as verr:
+
+ # Create temporary YAML file:
+ with tempfile.NamedTemporaryFile() as temp:
+ temp.write(_DUPLICATE_IDS_XML.encode())
+ temp.flush()
+
+ _ = ParamGen.from_xml_nml(temp.name, no_duplicates=True)
+
+ emsg = "Entry id 'foo' listed twice in file:\n'./xml_test_files/duplicate_ids.xml'"
+ self.assertEqual(emsg, str(verr.exception))
+
+
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+#!/usr/bin/env python3
+
+import unittest
+import os
+import shutil
+import tempfile
+from CIME.SystemTests.test_utils import user_nl_utils
+
+
+
+[docs]
+class TestUserNLCopier(unittest.TestCase):
+
+ # ========================================================================
+ # Test helper functions
+ # ========================================================================
+
+
+
+
+
+
+
+
+[docs]
+ def write_user_nl_file(self, component, contents, suffix=""):
+ """Write contents to a user_nl file in the case directory. Returns the
+ basename (i.e., not the full path) of the file that is created.
+
+ For a component foo, with the default suffix of '', the file name will
+ be user_nl_foo
+
+ If the suffix is '_0001', the file name will be user_nl_foo_0001
+ """
+
+ filename = "user_nl_" + component + suffix
+
+ with open(os.path.join(self._caseroot, filename), "w") as user_nl_file:
+ user_nl_file.write(contents)
+
+ return filename
+
+
+
+[docs]
+ def assertFileContentsEqual(self, expected, filepath, msg=None):
+ """Asserts that the contents of the file given by 'filepath' are equal to
+ the string given by 'expected'. 'msg' gives an optional message to be
+ printed if the assertion fails."""
+
+ with open(filepath, "r") as myfile:
+ contents = myfile.read()
+
+ self.assertEqual(expected, contents, msg=msg)
+
+
+ # ========================================================================
+ # Begin actual tests
+ # ========================================================================
+
+
+[docs]
+ def test_append(self):
+ # Define some variables
+ component = "foo"
+ # deliberately exclude new line from file contents, to make sure that's
+ # handled correctly
+ orig_contents = "bar = 42"
+ contents_to_append = "baz = 101"
+
+ # Setup
+ filename = self.write_user_nl_file(component, orig_contents)
+
+ # Exercise
+ user_nl_utils.append_to_user_nl_files(
+ caseroot=self._caseroot, component=component, contents=contents_to_append
+ )
+
+ # Verify
+ expected_contents = orig_contents + "\n" + contents_to_append + "\n"
+ self.assertFileContentsEqual(
+ expected_contents, os.path.join(self._caseroot, filename)
+ )
+
+
+
+[docs]
+ def test_append_list(self):
+ # Define some variables
+ component = "foo"
+ # deliberately exclude new line from file contents, to make sure that's
+ # handled correctly
+ orig_contents = "bar = 42"
+ contents_to_append_1 = "baz = 101"
+ contents_to_append_2 = "qux = 987"
+ contents_to_append = [
+ contents_to_append_1,
+ contents_to_append_2,
+ ]
+
+ # Setup
+ filename = self.write_user_nl_file(component, orig_contents)
+
+ # Exercise
+ user_nl_utils.append_to_user_nl_files(
+ caseroot=self._caseroot, component=component, contents=contents_to_append
+ )
+
+ # Verify
+ expected_contents = (
+ orig_contents
+ + "\n"
+ + contents_to_append_1
+ + "\n"
+ + contents_to_append_2
+ + "\n"
+ )
+ self.assertFileContentsEqual(
+ expected_contents, os.path.join(self._caseroot, filename)
+ )
+
+
+
+[docs]
+ def test_append_multiple_files(self):
+ # Simulates a multi-instance test
+ component = "foo"
+ orig_contents1 = "bar = 42"
+ orig_contents2 = "bar = 17"
+ contents_to_append = "baz = 101"
+
+ # Setup
+ filename1 = self.write_user_nl_file(component, orig_contents1, suffix="_0001")
+ filename2 = self.write_user_nl_file(component, orig_contents2, suffix="_0002")
+
+ # Exercise
+ user_nl_utils.append_to_user_nl_files(
+ caseroot=self._caseroot, component=component, contents=contents_to_append
+ )
+
+ # Verify
+ expected_contents1 = orig_contents1 + "\n" + contents_to_append + "\n"
+ expected_contents2 = orig_contents2 + "\n" + contents_to_append + "\n"
+ self.assertFileContentsEqual(
+ expected_contents1, os.path.join(self._caseroot, filename1)
+ )
+ self.assertFileContentsEqual(
+ expected_contents2, os.path.join(self._caseroot, filename2)
+ )
+
+
+
+[docs]
+ def test_append_without_files_raises_exception(self):
+ # This test verifies that you get an exception if you call
+ # append_to_user_nl_files when there are no user_nl files of interest
+
+ # Define some variables
+ component_exists = "foo"
+ component_for_append = "bar"
+
+ # Setup
+ # Create file in caseroot for component_exists, but not for component_for_append
+ self.write_user_nl_file(component_exists, "irrelevant contents")
+
+ self.assertRaisesRegex(
+ RuntimeError,
+ "No user_nl files found",
+ user_nl_utils.append_to_user_nl_files,
+ caseroot=self._caseroot,
+ component=component_for_append,
+ contents="irrelevant contents to append",
+ )
+
+
+
+
+if __name__ == "__main__":
+ unittest.main()
+
' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/branch/rljacob/docs/update-testing/html/build_cpl/adding-components.html b/branch/rljacob/docs/update-testing/html/build_cpl/adding-components.html new file mode 100644 index 00000000000..5309e73c4fd --- /dev/null +++ b/branch/rljacob/docs/update-testing/html/build_cpl/adding-components.html @@ -0,0 +1,198 @@ + + + + + + +Here are the steps to add prognostic components to CIME models.
+There are a couple of aspects of a component interface to CIME, the +scripts interface which controls setting up component inputs and +building the component and the run interface which controls connecting +the component to the coupler and through the coupler, the other +components of the CIME based model.
+The component should have a subdirectory cime_config and this +subdirectory should have two files buildnml and buildlib The +buildnml script is used to build the components instructional, +runtime inputs. These have traditionally been in the form of fortran +namelists but may also follow other formats. The buildnml may +either be called from the command line or as a python subroutine. If +buildnml is called from the command line it will be passed the +caseroot directory on the command line. If it is called as a +subroutine, the subroutine name must be buildnml and it will take +three arguments, a Case object, a caseroot directory and a component +name. The buildlib script will always be called from the command +line, it is called in the case.build step and is expected to build the +the buildlib script will be called with three arguments in order they +are caseroot, libroot (the location of the installed library, +typically EXEROOT/lib) and bldroot, the location of the component +build directory. Look at the cime internal components such as datm +for an example.
+The coupler interface is dependent on which coupler is used, for the mct coupler in cime +the component model must provide NNN_INIT_MCT, NNN_RUN_MCT, NNN_FINAL_MCT where NNN is the +component type of the particular component (eg ATM for an atmosphere, LND for a land model) +these subroutines are expected to be in the component library.
+Content to go here:
+How to add a new component model to cime.
+How to replace an existing cime model with another one.
+How to integrate your model in to the cime build/configure system and coupler.
+How to work with the CIME-supplied models.
+What to do if you want to add another component to the long name.
++ | + |
|
+
|
+
|
+
|
+
|
+ + |
|
+
+ |
|
+
+ |
|
+
|
+
|
+ + |
+ |
|
+
|
+
|
+
|
+
+ | + |
|
+ + |
+ |
|
+
Solves a complex set of equations to describe a sub-model’s behavior.
+An instance of a global climate model simulation. A case is defined by a component set, a model grid, +a machine, a compiler, and any other additional customizations.
+A sub-model coupled with other components to constitute a global climate modeling system. +Example components: atmosphere, ocean, land, etc.
+A complete set of components to be linked together into a climate model to +run a specific case.
+Replacement for an active component. Sends and receives the same variables to and from other +models (but ignores the variables received).
+A set of numerical grids of a case. Each active component operates on its own numerical grid.
+Used to refer to a set of grids. Each grid within a set may have different resolution.
+Simply occupies the required place in the climate execution sequence and does send or receive +any data.
+A component of the CIME infrastructure that is run from within the driver. It can be run on a +subset of the total processors, and carries out mapping (interpolation), merging, diagnostics, and other +calculations.
+The hub that connects all components. CIME driver runs on all hardware processors, runs the top +level instructions, and, executes the driver time loop.
+An imposed perturbation of Earth’s energy balance
+A library used by CIME for all data rearranging and mapping (interpolation)
+Determines land/ocean boundaries in the model
+Interpolation of fields between components.
+If short term archiving is activated (DOUT_S = TRUE), the restart files and run output files +are copied to archive directory location (DOUT_S_ROOT).
+Location where the case is built.
+The directory where the case is created. Includes namelist files, xml files, and scripts to setup, +build, and run the case. Also, includes logs and timing output files.
+The directory where the CIME source code resides
+NetCDF files that contain fields associated with the state of the model at a given time slice.
+Files required to start a file
+A time-series of input data files where all the fields in the stream are located in the +same data file and all share the same spatial and temporal coordinates.
+Each namelist file includes input parameters for a specific component.
+Where the case is run.
+Written and read by each component in the RUNDIR to stop and subsequently restart in a bit-for-bit fashion.
+Text file written by the coupler in the RUNDIR with a list of necessary files required for model restart.
+Elements and attributes in these files configure a case. (building, running, batch, etc.) These files +include env_archive.xml, env_batch.xml, env_build.xml, env_case.xml, env_mach_pes.xml, env_mach_specific.xml, env_run.xml +in CASEROOT and can be queried and modifed using the xmlquery and xmlchange tools.
+A checked out tag on a local or a remote machine. may be edited to create a new tag. or, may +just be used for running cases.
+one or more source files that are modified by the user. Before building a case, CIME replaces +the original source files with these files.
+A snapshot of the source code. With each consecutive tag (one or more) answer-changing modifications +to the source code of a component are introduced.
+User modifications for a given case can be specified in these files.
+A set of test cases that is run using a tag which is complete, tested, and has no modifications +in the source code. Used to assess the performance/accuracy of a case that is run using a sandbox.
+A test that fails in its comparison with a baseline.
+Part of the unit testing framework used by CIME scripts regression tests.
+A test that compares with baseline results to determine if any new errors have been introduced +into the code base.
+A fast, self-verifying test of a small piece of code.
+External System Processing: handles data assimilation
+The Common Infrastructure for Modeling the Earth (CIME - pronounced +“SEAM”) provides a Case Control System for configuring, compiling and executing +Earth system models, data and stub model components, a driver and associated tools +and libraries.
+CESM-ECT is a suite of tests to determine whether a new +simulation set up (new machine, compiler, etc.) is statistically +distinguishable from an accepted ensemble. The verification tools in +the CESM-ECT suite are:
+CAM-ECT - detects issues in CAM and CLM (12 month runs) +UF-CAM-ECT - detects issues in CAM and CLM (9 time step runs) +POP-ECT - detects issues in POP and CICE (12 month runs)
+The ECT process involves comparing runs generated with +the new scenario ( 3 for CAM-ECT and UF-CAM-ECT, and 1 for POP-ECT) +to an ensemble built on a trusted machine (currently +cheyenne). The python ECT tools are located in the pyCECT +subdirectory or https://github.com/NCAR/PyCECT/releases.
+-OR-
+We now provide a web server for CAM-ECT and UF-CAM-ECT, where +you can upload the (3) generated runs for comparison to our ensemble. +Please see the webpage at http://www.cesm.ucar.edu/models/cesm2/verification/ +for further instructions.
+Before the test can be run, a summary file is needed of the ensemble +runs to which the comparison will be made. Ensemble summary files +(NetCDF) for existing tags for CAM-ECT, UF-CAM-ECT, and POP-ECT that +were created by CSEG are located (respectively) in the CESM input data +directories:
+$CESMDATAROOT/inputdata/validation/ensembles +$CESMDATAROOT/inputdata/validation/uf_ensembles +$CESMDATAROOT/inputdata/validation/pop_ensembles
+If none of our ensembles are suitable for your needs, then you may create +your own ensemble (and summary file) using the following instructions:
+(1) To create a new ensemble, use the ensemble.py script in this directory. +This script creates and compiles a case, then creates clones of the +original case, where the initial temperature perturbation is slightly modified +for each ensemble member. At this time, cime includes functionality +to create ensembles for CAM-ECT, UF-CAM-ECT, and POP-ECT.
+(2) Use –ect <pop,cam> to specify whether ensemble is for CAM or POP. +(See ‘python ensemble.py -h’ for additional details).
+(3) Use –ensemble <size> to specify the ensemble size. +Recommended ensemble sizes: +CAM-ECT: 151 +UF-CAM-ECT: 350 +POP-ECT 40
+Examples:
CAM-ECT:
+python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/ensemble/ensemble.cesm_tag.000 –mach cheyenne –ensemble 151 –ect cam –project P99999999
+UF-CAM-ECT:
+python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/uf_ensemble/ensemble.cesm_tag.uf.000 –mach cheyenne –ensemble 350 –uf –ect cam –project P99999999
+POP-ECT:
+python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/uf_ensemble/ensemble.cesm_tag.000 –mach cheyenne –ensemble 40 –ect pop –project P99999999
+ensemble.py accepts (most of) the argumenets of create_newcase
case name must end in “.000” and include the full path
ensemble size must be specified, and suggested defaults are listed +above. Note that for CAM-ECT and UF-CAM-ECT, the ensemble size +needs to be larger than the number of variables that ECT will evaluate.
(5) Once all ensemble simulations have run successfully, copy every cam history +file (.cam.h0.) for CAM-ECT and UF-CAM-ECT) or monthly pop history file +(.pop.h.) for POP-ECT from each ensemble run directory into a separate directory. +Next create the ensemble summary using the pyCECT tool pyEnsSum.py (for CAM-ECT and +UF-CAM-ECT) or pyEnsSumPop.py (for POP-ECT). For details see README_pyEnsSum.rst +and README_pyEnsSumPop.rst with the pyCECT tools.
+(1) Once an ensemble summary file has been created or chosen to +use from $CESMDATAROOT/inputdata/validation, the simulation +run(s) to be verified by ECT must be created via script ensemble.py.
+NOTE: It is important that the same resolution and compset be used in the +individual runs as in the ensemble. The NetCDF ensemble summary file global +attributes give this information.
+For example, for CAM-ECT:
python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/camcase.cesm_tag.000 –ect cam –mach cheyenne –project P99999999 +–compset F2000climo –res f19_f19 +For example, for UF-CAM-ECT:
+python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/uf.camcase.cesm_tag.000 –ect cam –uf –mach cheyenne –project P99999999 –compset F2000climo –res f19_f19
+For example, for POP-ECT:
+python ensemble.py –case /glade/scratch/cesm_user/cesm_tag/popcase.cesm_tag.000 –ect pop –mach cheyenne –project P99999999 –compset G –res T62_g17
+(3) Next verify the new simulation(s) with the pyCECT tool pyCECT.py (see +README_pyCECT.rst with the pyCECT tools).
+In addition to basic infrastructure for a coupled model, CIME contains in its distribution several stand-alone +tools that are necessary and/or useful when building a climate model. Guides for using them will be here.
+ +++Originally Developed by Sheri Mickelson mickelso@ucar.edu +and Yuri Alekseev (ALCF/Argonne National Laboratory
+Updated 2017 Jason Sarich sarich@mcs.anl.gov (Argonne National Laboratory)
+
This Load Balancing tool performs several operations intended to find +a reasonable PE layout for CIME simulations. These operations involve two +steps:
+1. load_balancing_submit.py
+ Run a series of simulations in order to obtain timing data
+
+2. load_balancing_solve.py
+ Using the data provided in the previous program, solve a mixed integer
+ linear program to optimize the model throughput. Requires installation
+ of PuLP and uses the included COIN-CBC solver. (https://pythonhosted.org/PuLP)
+
Also in this documentation is:
+3. More about the algorithm used
+
+4. Extending the solver for other models
+
+5. Testing information for developers
+
For the impatient
+set PYTHONPATH to include $CIME_DIR/scripts:$CIME_DIR/tools/load_balancing_tool
create PE XML <PESFILE> file to describe the PE layouts for the timing runs
$ ./load_balancing_submit.py –res <RESOLUTION> –compset <COMPSET> –pesfile <PESFILE>
… wait for jobs to run …
$ ./load_balancing_solve.py –total-tasks <N> –blocksize 8
Simulations can be run on a given system by executing the load_balancing_tool.py +script, located in cime/tools/load_balancing_tool/load_balancing_tool_submit.py. +This creates timing files in the case directory which will be used to solve +a mixed integer linear program optimizing the layout. If there is already timing +information available, then a
+As with the create_newcase and create_test scripts, command line options +are used to tailor the simulations for a given model. These values will be +directly forwarded to the passed:
+--compiler
+--project
+--compset (required)
+--res (required)
+--machine
+
Other options include:
+--pesfile <filename> (required)
+ This file is used to designated the pes layout that
+ are used to create the timing data. The format is the same used
+ by CIME pes_files, but note that the 'pesize' tag will be used
+ to generate the casename. Also, this file will not be directly
+ passed through to CIME, but rather it will trigger xmlchange
+ commands to execute based on the values in the file.
+
+--test-id <prefix>
+ By default, the load balancing tool will use casenames:
+ PFS_I0.res.compset.lbt
+ PFS_I1.res.compset.lbt
+ ...
+ PFS_IN.res.compset.lbt
+ for each simulation requested. These casenames will be forwarded to
+ the create_test script.
+
+ Using this option will instead direct the tool to use:
+ PFS_I0.res.compset.test-id
+ PFS_I1.res.compset.test-id
+ ...
+ PFS_IN.res.compset.test-id
+
+--force-purge
+ Force the tool to remove any existing case directories if they
+ exist. Removes PFS_I*.res.compset.test-id
+
+--extra-options-file
+ Add extra xml options to the timing runs from a user file,
+ these options will be set after create_newcase and before
+ case.setup.
+ This text file should have one variable per line in
+ the format <var>=<value>. Example:
+
+ STOP_OPTION=ndays
+ STOP_N=7
+ DOUT_S=FALSE
+
Reads timing data created with load_balancing_submit.py (or otherwise, +see –timing-files option) and solves an mixed integer optimization problem +using these timings. The default layout (IceLndAtmOcn) minimizes the cost per +model day assuming the layout:
+ ____________________
+| ICE | LND | |
+|______|_______| |
+| | OCN |
+| ATM | |
+|______________|_____|
+
An IceLndWavAtmOcn layout is also available. It is possible to extend +this tool to solve for other layouts (See Section 1.4 Extending the Load +Balancing Tool)
+Note – threading is not considered part of this optimization, it is assumed that +all timing data have the same threading structure (i.e. all ATM runs use two threads per PE)
+Options recognized by the solver:
+--layout <class_name>
+ Name of the class used to solve the layout problem. The only built-in
+ class at this time is the default IceLndAtmOcn, but this can be extended.
+ See section 4 Extending the Load Balancing Tool
+
+--total-tasks N (required)
+ The total number of PEs that can be assigned
+
+--timing-dir <dir>
+ Optional, read in all files from this directory as timing data
+
+--test-id <prefix>
+ The test-id used when submitting the timing jobs. This option can also
+ be used to set a single directory where ALL of the timing data is.
+ The solver will extract data from timing files that match either pattern:
+ <prefix>.test-id/timing/timing.<prefix>.test-id
+ <prefix>.test-id/timing/timing.<prefix>.test-id
+
+--blocksize N
+ The blocksize is the granularity of processors that will be group
+ together, useful for when PEs to be multiples of 8, 16, etc.
+
+--blocksize-XXX N
+ Components don't all have to have the same blocksize. The default
+ blocksize given by --blocksize can be overridden for a given component
+ using this option, where XXX can be ATM, ICE, GLC, etc.
+ Example:
+ --blocksize 8 --blocksize-GLC 1
+ will set the GLC blocksize to 1 and all other blocksizes to 8
+
+--milp-output <filename>
+ After extracting data from timing files and before solving, write the
+ data to a .json file where is can be analyzed or manually edited.
+
+--milp-input <filename>
+ Read in the problem from the given .json file instead of extracting from
+ timing files.
+
+--pe-output <filename>
+ Write the solution PE layout to a potential pe xml file.
+
Before solving the mixed-integer linear program, a model of the cost vs ntasks +function is constructed for each component.
+Given a component data set of costs (C1,C2,..,Cn) and nblocks (N1,N2,..,Nn), +then an piecewise set of n+1 linear constraints are created using the idea:
+If N < N1 (which means that N1 cannot be 1), then assume that there is +perfect scalability from N to N1. Thus the cost is on the line +defined by the points (1, C1*N1) - (N1, C1).
+If N is between N_i and N_{i+1}, then the cost is on the line defined by the +points (N_i, C_i) and (N_{i+1}, C_{i+1}.
+If N > Nn, then we want to extrapolate the cost at N=total_tasks +(we define N{n+1} = total_tasks, C{n+1} = estimated cost using all nodes) +Assuming perfect scalability is problematic at this level, so we instead +assume that the parallel efficiency drops at the same factor as it does
+++from N=N{n-1} to N = Nn
+++First solve for efficiency E: +C{n-1} - Cn = E * (C{n-1} * N{n-1} / Nn)
+Then E to find C{n+1} (cost at ntasks N{n+1}): +Cn - Ct = E * (Cn * Nn / Nt)
+Now cost is on the line defined by (Nn,Cn) - (Nt,Ct)
+
Assuming that this piecewise linear function describes a convex function, we do +not have to explicitly construct this piecewise function and can instead use +each of the cost functions on the entire domain.
+These piecewise linear models give us the following linear constraints, where +the model time cost C as a function of N (ntasks) for each component +is constrained by:
+C >= Ci - Ni * (C{i+1}-Ci) / (N{i+1}-Ni) +
+ N * (C{i+1}-Ci) / (N{i+1}-Ni) for i=0..n
+
These constraints should be in effect for any extensions of the solver (the +components involved may be different).
+There are options available in load_balancing_submit.py to inspect these +piecewise linear models:
+--graph-models (requires matplotlib)
+--print-models (debugging modes writes the models to the log)
+
Now that these constraints are defined, the mixed integer linear program (MILP) +follows from the layout:
+NOTES: variable N[c] is number of tasks assigned for component c
+ variable NB[c] is the number of blocks assigned to component c
+ constant C[c]_i is the cost contributed by component c from
+ timing data set i
+ constant N[c]_i is the ntasks assigned to component c from
+ timing data set i
+
+ ____________________
+ | ICE | LND | |
+ T1 |______|_______| |
+ | | OCN |
+ | ATM | |
+ T |______________|_____|
+
+ Min T
+ s.t. Tice <= T1
+ Tlnd <= T1
+ T1 + Tatm <= T
+ Tocn <= T
+
+ NB[c] >= 1 for c in [ice,lnd,ocn,atm]
+ N[ice] + N[lnd] <= N[atm]
+ N[atm] + N[ocn] <= TotalTasks
+ N[c] = blocksize * NB[c], for c in [ice,lnd,ocn,atm]
+
+
+ T[c] >= C[c]_{i} - N[c]_{i} *
+ (C[c]_{i+1} - C[c]_{i}) / (N[c]_{i+1} - N[c]_{i})
+ + N[c] * (C[c]_{i+1} - C[c]_{i})
+ / (N[c]_{i+1} - N[c]_{i}),
+ for i=0..#data points (original + extrapolated,
+ c in [ice,lnd,ocn,atm]
+ all T vars >=0
+ all N,NB vars integer
+
This MILP is solved using the PuLP python interface to the COIN-CBC solver +https://pythonhosted.org/PuLP/ +https://www.coin-or.org/Cbc/
+The file $CIME_DIR/tools/load_balancing_tool/optimize_model.py +contains a base class OptimizeModel as well as an implementation class +IceLndAtmOcn. Any layout solver will look similar to IceLndAtmOcn +except for the components involved and the layout-specific constraints.
+Example class and inherited methods that should be overridden:
+file my_new_layout.py:
+import optimize_model
+
+class MyNewLayout(optimize_model.OptimizeModel)
+ def get_required_components(self):
+ """
+ Should be overridden by derived class. Return a list of required
+ components (capitalized) used in the layout.
+ Example: return ['ATM', 'LND', 'ICE']
+ """
+
+ def optimize(self):
+ """
+ Run the optimization.
+ Must set self.state using LpStatus object
+ LpStatusOptimal -> STATE_SOLVED_OK
+ LpStatusNotSolved -> STATE_UNSOLVED
+ LpStatusInfeasible -> STATE_SOLVED_BAD
+ LpStatusUnbounded -> STATE_SOLVED_BAD
+ LpStatusUndefined -> STATE_UNDEFINED
+ -- use self.set_state(lpstatus) --
+ Returns state
+
+ If solved, then solution will be stored in self.X dictionary, indexed
+ by variable name. Suggested convention:
+ 'Tice', 'Tlnd', ... for cost per component
+ 'Nice', 'Nlnd', ... for ntasks per component
+ 'NBice', 'NBlnd', ... for number of blocks per component
+
+ The default implementation of get_solution() returns a dictionary
+ of these variable keys and their values.
+ """
+
+ def get_solution(self):
+ """
+ Return a dictionary of the solution variables, can be overridden.
+ Default implementation returns values in self.X
+ """
+
save the class MyNewLayout in file my_new_layout.py
make sure that my_new_layout.py is in PYTHONPATH
Use those names in your execution command line argument to –layout
+$ ./load_balancing_solve.py ... --layout my_new_layout.MyNewLayout
+
To permanently add to CIME:
++++
+- +
add MyNewLayout class to layouts.py
- +
run using ‘–layout MyNewLayout’
- +
add test in tests/load_balance_test.py that uses that name in command +line argument (see test for atm_lnd)
- +
make pull request
To run the provided test suite:
++++
+- +
set PYTHONPATH to include CIME libraries:
+++$ export CIME_DIR=/path/to/cime +$ export PYTHONPATH=$CIME_DIR/scripts:$CIME_DIR/tools/load_balancing_tool +- +
To run an example:
+++$ cd $CIME_DIR/tools/load_balancing_tool +$ ./load_balancing_solve.py --json-input tests/example.json --blocksize 8 +Solving Mixed Integer Linear Program using PuLP interface to COIN-CBC +PuLP solver status: Solved +COST_ATM = 22.567587 +COST_ICE = 1.375768 +COST_LND = 1.316000 +COST_OCN = 15.745000 +COST_TOTAL = 23.943355 +NBLOCKS_ATM = 124 +NBLOCKS_ICE = 109 +NBLOCKS_LND = 15 +NBLOCKS_OCN = 4 +NTASKS_ATM = 992 +NTASKS_ICE = 872 +NTASKS_LND = 120 +NTASKS_OCN = 32 +NTASKS_TOTAL = 1024 +- +
To run the test suite:
+++$ cd $CIME_DIR/tools/load_balancing_tool +$ ./tests/load_balancing_test.py +
+ c | ||
+ |
+ CIME | + |
+ |
+ CIME.baselines | + |
+ |
+ CIME.build_scripts | + |
+ |
+ CIME.BuildTools | + |
+ |
+ CIME.data | + |
+ |
+ CIME.data.config | + |
+ |
+ CIME.data.templates | + |
+ |
+ CIME.scripts | + |
+ |
+ CIME.SystemTests | + |
+ |
+ CIME.SystemTests.test_utils | + |
+ |
+ CIME.SystemTests.test_utils.user_nl_utils | + |
+ |
+ CIME.tests | + |
+ |
+ CIME.tests.case_fake | + |
+ |
+ CIME.tests.test_unit_case_fake | + |
+ |
+ CIME.tests.test_unit_paramgen | + |
+ |
+ CIME.tests.test_unit_user_nl_utils | + |
+ |
+ CIME.Tools | + |
+ |
+ CIME.XML | + |
+ t | ||
+ |
+ Tools | + |
Once the case has been created and setup, its time to build the executable. +Several directories full of source code must be built all with the same compiler and flags. +case.build performs all build operations (setting dependecies, invoking Make, +creating the executable).
+After calling case.setup , run case.build to build the model executable. Running this will:
+Create the component namelists in $RUNDIR
and $CASEROOT/CaseDocs
.
Create the necessary compiled libraries used by coupler and component models mct
, pio
, gptl
and csm_share
.
+The libraries will be placed in a path below $SHAREDLIBROOT
.
Create the necessary compiled libraries for each component model. These are be placed in $EXEROOT/bld/lib
.
Create the model executable ($MODEL.exe
), which is placed in $EXEROOT
.
You do not need to change the default build settings to create the executable, but it is useful to become familiar with them in order to make optimal use of the system. The CIME scripts provide you with a great deal of flexibility in customizing the build process.
+The env_build.xml variables control various aspects of building the executable. Most of the variables should not be modified, but users can modify these:
+$BUILD_THREADED
: if TRUE, the model will be built with OpenMP.
$DEBUG
: if TRUE, the model is compiled with debugging instead of optimization flags.
$GMAKE_J
: How many threads GNUMake should use while building.
The best way to see what xml variables are in your $CASEROOT
directory is to use the xmlquery command. For usage information, run:
> ./xmlquery --help
+
To build the model, change to your $CASEROOT
directory and execute case.build.
> cd $CASEROOT
+> ./case.build
+
Diagnostic comments appear as the build proceeds.
+The case.build command generates the utility and component libraries and the model executable, and it generates build logs for each component.
+Each log file is named form: $component.bldlog.$datestamp. They are located in $BLDDIR
. If they are compressed (as indicated by a .gz file extension), the build ran successfully.
Invoking case.build creates the following directory structure in $EXEROOT
if the Intel compiler is used:
atm/, cpl/, esp/, glc/, ice/, intel/, lib/, lnd/, ocn/, rof/, wav/
+
Except for intel/ and lib/, each directory contains an obj/ subdirectory for the target model component’s compiled object files.
+The mct, pio, gptl and csm_share libraries are placed in a directory tree that reflects their dependencies. See the bldlog for a given component to locate the library.
+Special include modules are placed in lib/include. The model executable (cesm.exe or e3sm.exe, for example) is placed directly in $EXEROOT
.
Component namelists, component logs, output data sets, and restart files are placed in $RUNDIR
.
+It is important to note that $RUNDIR
and $EXEROOT
are independent variables that are set in the $CASEROOT/env_run.xml file.
Rebuild the model under the following circumstances:
+If either env_build.xml or Macros.make has been modified, and/or if code is added to SourceMods/src., it’s safest to clean the build and rebuild from scratch as shown here:
+> cd $CASEROOT
+> ./case.build --clean-all
+
If you have ONLY modified the PE layout in env_mach_pes.xml, a clean may not be required.
+> cd $CASEROOT
+> ./case.build
+
If the threading has been changed (turned on or off) in any component since the previous build, the build script should fail with the following error and suggestion that the model be rebuilt from scratch:
+ERROR SMP STATUS HAS CHANGED
+SMP_BUILD = a0l0i0o0g0c0
+SMP_VALUE = a1l0i0o0g0c0
+A manual clean of your obj directories is strongly recommended.
+You should execute the following:
+ ./case.build --clean
+ ./case.build
+
+ ---- OR ----
+
+ You can override this error message at your own risk by executing:
+ ./xmlchange SMP_BUILD=0
+ Then rerun the build script interactively.
+
If there is any doubt, rebuild.
+> case.build --clean
+
> case.build --clean-all
+
> case.build --clean compname
+
Review the help text for more information.
+All active components and data components use input data sets. In order to run CIME and the CIME-compliant active components, a local disk needs the directory tree that is specified by the xml variable $DIN_LOC_ROOT
to be populated with input data.
Input data is provided as part of the CIME release via data from a subversion input data server. It is downloaded from the server on an as-needed basis determined by the case. Data may already exist in the default local file system’s input data area as specified by $DIN_LOC_ROOT
.
Input data can occupy significant space on a system, so users should share a common $DIN_LOC_ROOT
directory on each system if possible.
The build process handles input data as follows:
+The buildnml scripts in the various component cime_config
directories create listings of required component input data sets in the Buildconf/$component.input_data_list
files.
check_input_data , which is called by case.build , checks for the presence of the required input data files in the root directory $DIN_LOC_ROOT
.
If all required data sets are found on the local disk, the build can proceed.
If any of the required input data sets are not found locally, the +files that are missing are listed. At this point, you must obtain +the required data from the input data server with check_input_data as shown here:
+check_input_data --download
+
The env_run.xml variables $DIN_LOC_ROOT
and $DIN_LOC_ROOT_CLMFORC
determine where you should expect input data to reside on a local disk.
CIME and CIME-compliant components primarily use Fortran namelists to control runtime options. Some components use +other text-based files for runtime options.
+All CIME-compliant components generate their input variable files using a buildnml script typically located in the +component’s cime_config directory (or other location as set in config_file.xml). +buildnml may call other scripts to complete construction of the input file.
+For example, the CIME data atmosphere model (DATM) generates namelists using the script $CIMEROOT/components/data_comps/datm/cime_config/buildnml.
+You can customize a model’s namelists in one of two ways:
+by editing the $CASEROOT/user_nl_xxx files
++These files should be modified via keyword-value pairs that correspond to new namelist or input data settings. They use the +syntax of Fortran namelists.
+
by calling xmlchange to modify xml variables in your $CASEROOT
.
Many of these variables are converted to Fortran namelist values for input by the models. Variables that have +to be coordinated between models in a coupled system (such as how many steps to run for) are usually in a CIME xml file.
+You can generate the component namelists by running preview_namelists from $CASEROOT
.
This results in the creation of component namelists (for example, atm_in, lnd_in, and so on) in $CASEROOT/CaseDocs/
.
Warning
+The namelist files in CaseDocs
are there only for user reference and SHOULD NOT BE EDITED since they are overwritten every time preview_namelists and case.submit are called and the files read at runtime are not the ones in CaseDocs
.
The driver input namelists/variables are contained in the files, drv_in, drv_flds_in and seq_maps.rc. Note that seq_maps.rc has a different file format than the other two input files.
+All driver namelist variables are defined in the file $CIMEROOT/src/drivers/mct/cime_config/namelist_definition_drv.xml.
+The variables that can be changed only by modifying xml variables appear with the entry attribute modify_via_xml="xml_variable_name"
.
All other driver namelist variables can be modified by by adding a keyword value pair at the end of user_nl_cpl
.
For example, to change the driver namelist value of eps_frac
to 1.0e-15
, add the following line to the end of the user_nl_cpl
:
eps_frac = 1.0e-15
+
On the hand, to change the driver namelist value of the starting year/month/day, start_ymd
to 18500901
, use the command:
./xmlchange RUN_STARTDATE=1850-09-01
+
Note that
+To see the result of change, call preview_namelists and verify that the new value appears in CaseDocs/drv_in.
+This shows all of the steps necessary to do a multi-year simulation starting from a “cold start” for all components. The +compset and resolution in this example are for a CESM fully-coupled case but the steps are similar for other models and cases.
+Create a new case named EXAMPLE_CASE in your $HOME directory.
+> cd $CIME/scripts
+> ./create_newcase --case ~/EXAMPLE_CASE --compset B1850 --res f09_g17
+
Check the pe-layout by running ./pelayout. Make sure it is suitable for your machine. +If it is not use xmlchange or pelayout to modify your pe-layout. +Then setup your case and build your executable.
+> cd ~/EXAMPLE_CASE
+> ./case.setup
+> ./case.build
+
Warning
+The case.build script can be compute intensive and may not be suitable to run on a login node. As an alternative you would submit this job to an interactive queue. +For example, on the NCAR cheyenne platform, you would use qcmd – ./case.build to do this.
+In your case directory, set the job to run 12 model months, set the wallclock time, and submit the job.
+> ./xmlchange STOP_OPTION=nmonths
+> ./xmlchange STOP_N=12
+> ./xmlchange JOB_WALLCLOCK_TIME=06:00 --subgroup case.run
+> ./case.submit
+
Make sure the run succeeded.
+You should see the following line or similar at the end of the cpl.log file in your run directory or your short term archiving directory, set by $DOUT_S_ROOT
.
(seq_mct_drv): =============== SUCCESSFUL TERMINATION OF CPL7-cesm ===============
+
In the same case directory, Set the case to resubmit itself 10 times so it will run a total of 11 years (including the initial year), and resubmit the case. (Note that a resubmit will automatically change the run to be a continuation run).
+> ./xmlchange RESUBMIT=10
+> ./case.submit
+
By default resubmitted runs are not submitted until the previous run is completed. For 10 1-year runs as configured in this +example, CIME will first submit a job for one year, then when that job completes it will submit a job for another year. There will be +only one job in the queue at a time. +To change this behavior, and submit all jobs at once (with batch dependencies such that only one job is run at a time), use the command:
+> ./case.submit --resubmit-immediate
+
A branch or hybrid run uses initialization data from a previous run. Here is an example in which a valid load-balanced scenario is assumed.
+The first step in setting up a branch or hybrid run is to create a new case. A CESM compset and resolution is assumed below.
+> cd $CIMEROOT/scripts
+> create_newcase --case ~/NEW_CASE --compset B1850 --res f09_g17
+> cd ~/NEW_CASE
+
For a branch run, use the following xmlchange commands to make NEW_CASE be a branch off of EXAMPLE_CASE at year 0001-02-01.
+> ./xmlchange RUN_TYPE=branch
+> ./xmlchange RUN_REFCASE=EXAMPLE_CASE
+> ./xmlchange RUN_REFDATE=0001-02-01
+
For a hybrid run, use the following xmlchange command to start NEW_CASE from EXAMPLE_CASE at year 0001-02-01.
+> ./xmlchange RUN_TYPE=hybrid
+> ./xmlchange RUN_REFCASE=EXAMPLE_CASE
+> ./xmlchange RUN_REFDATE=0001-02-01
+
For a branch run, your env_run.xml file for NEW_CASE should be identical to the file for EXAMPLE_CASE except for the $RUN_TYPE
setting.
Also, modifications introduced into user_nl_ files in EXAMPLE_CASE should be reintroduced in NEW_CASE.
+Next, set up and build your case executable.
+> ./case.setup
+> ./case.build
+
Pre-stage the necessary restart/initial data in $RUNDIR
. Assume for this example that it was created in the /rest/0001-02-01-00000 directory shown here:
> cd $RUNDIR +> cp /user/archive/EXAMPLE_CASE/rest/0001-02-01-00000/* .
+It is assumed that you already have a valid load-balanced scenario. +Go back to the case directory, set the job to run 12 model months, and submit the job.
+> cd ~/NEW_CASE
+> ./xmlchange STOP_OPTION=nmonths
+> ./xmlchange STOP_N=12
+> ./xmlchange JOB_WALLCLOCK_TIME=06:00
+> ./case.submit
+
Make sure the run succeeded (see above directions) and then change +the run to a continuation run. Set it to resubmit itself 10 times +so it will run a total of 11 years (including the initial year), +then resubmit the case.
+> ./xmlchange CONTINUE_RUN=TRUE
+> ./xmlchange RESUMIT=10
+> ./case.submit
+
Each data model can be runtime-configured with its own namelist.
+DATM is discussed in detail in data atmosphere overview (link currently broken). +DATM can be user-customized by changing either its namelist input files or its stream files. +The namelist file for DATM is datm_in (or datm_in_NNN for multiple instances).
+To modify datm_in or datm_in_NNN, add the appropriate keyword/value pair(s) for the namelist changes that you want at the end of the user_nl_datm file or the user_nl_datm_NNN file in $CASEROOT
.
To modify the contents of a DATM stream file, first run preview_namelists to list the streams.txt files in the CaseDocs/ directory. Then, in the same directory:
+> cp datm.streams.txt.[extension] user_datm.streams.txt[extension.
chmod 644 user_datm.streams.txt[extension
Edit the user_datm.streams.txt.* file.
Example
+If the stream txt file is datm.streams.txt.CORE2_NYF.GISS, the modified copy should be user_datm.streams.txt.CORE2_NYF.GISS. +After calling preview_namelists again, your edits should appear in CaseDocs/datm.streams.txt.CORE2_NYF.GISS.
+DOCN is discussed in detail in data ocean overview (link currently broken). +DOCN can be user-customized by changing either its namelist input or its stream files. +The namelist file for DOCN is docn_in (or docn_in_NNN for multiple instances).
+To modify docn_in or docn_in_NNN, add the appropriate keyword/value pair(s) for the namelist changes that you want at the end of the file in $CASEROOT
.
To modify the contents of a DOCN stream file, first run preview_namelists to list the streams.txt files in the CaseDocs/ directory. Then, in the same directory:
+> cp docn.streams.txt.[extension] user_docn.streams.txt[extension.
chmod 644 user_docn.streams.txt[extension
Edit the user_docn.streams.txt.* file.
Example
+As an example, if the stream text file is docn.stream.txt.prescribed, the modified copy should be user_docn.streams.txt.prescribed. +After changing this file and calling preview_namelists again, your edits should appear in CaseDocs/docn.streams.txt.prescribed.
+DICE is discussed in detail in data sea-ice overview (link currently broken).
+DICE can be user-customized by changing either its namelist input or its stream files.
+The namelist file for DICE is dice_in
(or dice_in_NNN
for multiple instances) and its values can be changed by editing the $CASEROOT
file user_nl_dice
(or user_nl_dice_NNN
for multiple instances).
To modify dice_in or dice_in_NNN, add the appropriate keyword/value pair(s) for the namelist changes that you want at the end of the file in $CASEROOT
.
To modify the contents of a DICE stream file, first run preview_namelists to list the streams.txt files in the CaseDocs/ directory. Then, in the same directory:
+> cp dice.streams.txt.[extension] user_dice.streams.txt[extension.
chmod 644 user_dice.streams.txt[extension
Edit the user_dice.streams.txt.* file.
DLND is discussed in detail in data land overview (link currently broken).
+DLND can be user-customized by changing either its namelist input or its stream files.
+The namelist file for DLND is dlnd_in
(or dlnd_in_NNN
for multiple instances) and its values can be changed by editing the $CASEROOT
file user_nl_dlnd
(or user_nl_dlnd_NNN
for multiple instances).
To modify dlnd_in or dlnd_in_NNN, add the appropriate keyword/value pair(s) for the namelist changes that you want at the end of the file in $CASEROOT
.
To modify the contents of a DLND stream file, first run preview_namelists to list the streams.txt files in the CaseDocs/ directory. Then, in the same directory:
+> cp dlnd.streams.txt.[extension] user_dlnd.streams.txt[extension.
chmod 644 user_dlnd.streams.txt[extension
Edit the user_dlnd.streams.txt.* file.
DROF is discussed in detail in data river overview (link currently broken).
+DROF can be user-customized by changing either its namelist input or its stream files.
+The namelist file for DROF is drof_in
(or drof_in_NNN
for multiple instances) and its values can be changed by editing the $CASEROOT
file user_nl_drof
(or user_nl_drof_NNN
for multiple instances).
To modify drof_in or drof_in_NNN, add the appropriate keyword/value pair(s) for the namelist changes that you want at the end of the file in $CASEROOT
.
To modify the contents of a DROF stream file, first run preview_namelists to list the streams.txt files in the CaseDocs/ directory. Then, in the same directory:
+> cp drof.streams.txt.[extension] user_drof.streams.txt[extension.
chmod 644 user_drof.streams.txt[extension
Edit the user_drof.streams.txt.* file.
CIME calls $SRCROOT/components/cam/cime_config/buildnml to generate the CAM’s namelist variables.
+CAM-specific CIME xml variables are set in $SRCROOT/components/cam/cime_config/config_component.xml and are used by CAM’s buildnml script to generate the namelist.
+For complete documentation of namelist settings, see CAM namelist variables.
+To modify CAM namelist settings, add the appropriate keyword/value pair at the end of the $CASEROOT/user_nl_cam file. (See the documentation for each file at the top of that file.)
+For example, to change the solar constant to 1363.27, modify user_nl_cam file to contain the following line at the end:
+solar_const=1363.27
+
To see the result, call preview_namelists and verify that the new value appears in CaseDocs/atm_in.
+CIME calls $SRCROOT/components/clm/cime_config/buildnml to generate the CLM namelist variables.
+CLM-specific CIME xml variables are set in $SRCROOT/components/clm/cime_config/config_component.xml and are used by CLM’s buildnml script to generate the namelist.
+For complete documentation of namelist settings, see CLM namelist variables.
+To modify CLM namelist settings, add the appropriate keyword/value pair at the end of the $CASEROOT/user_nl_clm file.
+To see the result, call preview_namelists and verify that the changes appear correctly in CaseDocs/lnd_in.
+CIME calls $SRCROOT/components/mosart/cime_config/buildnml to generate the MOSART namelist variables.
+To modify MOSART namelist settings, add the appropriate keyword/value pair at the end of the $CASEROOT/user_nl_rtm file.
+To see the result of your change, call preview_namelists and verify that the changes appear correctly in CaseDocs/rof_in.
+CIME calls $SRCROOT/components/cice/cime_config/buildnml to generate the CICE namelist variables.
+For complete documentation of namelist settings, see CICE namelist variables.
+To modify CICE namelist settings, add the appropriate keyword/value pair at the end of the $CASEROOT/user_nl_cice file. +(See the documentation for each file at the top of that file.) +To see the result of your change, call preview_namelists and verify that the changes appear correctly in CaseDocs/ice_in.
+In addition, case.setup creates CICE’s compile time block decomposition variables in env_build.xml.
+CIME calls $SRCROOT/components/pop2/cime_config/buildnml to generate the POP2 namelist variables.
+For complete documentation of namelist settings, see POP2 namelist variables.
+To modify POP2 namelist settings, add the appropriate keyword/value pair at the end of the $CASEROOT/user_nl_pop2 file. +(See the documentation for each file at the top of that file.) +To see the result of your change, call preview_namelists and verify that the changes appear correctly in CaseDocs/ocn_in.
+See CISM namelist variables for a complete description of the CISM runtime namelist variables. This includes variables that appear both in cism_in and in cism.config.
+To modify any of these settings, add the appropriate keyword/value pair at the end of the user_nl_cism file. (See the documentation for each file at the top of that file.) +Note that there is no distinction between variables that will appear in cism_in and those that will appear in cism.config: simply add a new variable setting in user_nl_cism, and it will be added to the appropriate place in cism_in or cism.config. +To see the result of your change, call preview_namelists and verify that the changes appear correctly in CaseDocs/cism_in and CaseDocs/cism.config.
+Some CISM runtime settings are sets via env_run.xml, as documented in CISM runtime variables.
+CIME recognizes a user-created custom configuration directory, $HOME/.cime
. The contents of this directory may include any of the following files:
config
This file must have a format which follows the python config format. See Python Config Parser Examples
+In the [main] block you can set the following variables:
+CIME_MODEL=[e3sm, cesm]
PROJECT=<account number>
Used to specify a project id for compute accounting and directory permissions when on a batch system.
+CHARGE_ACCOUNT=<account number>
Used to override the accounting (only) aspect of PROJECT
+MAIL_USER=<email address>
Used to request a non-default email for batch summary output
+MAIL_TYPE=[never,all,begin,fail,end]
Any or all the above valid values can be set to list the batch events that emails will be sent for.
+create_test input arguments
+Any argument to the create_test script can have its default changed by listing it here with the new default.
+The following is an example config
file:
[main]
+CIME_MODEL=cesm
+SRCROOT=$CIMEROOT/..
+MAIL_TYPE=end
+[create_test]
+MAIL_TYPE=fail
+
config_machines.xml
This file must the same format as $CIMEROOT/config/$model/machines/config_machines.xml with the appropriate definitions for your machine.
+If you have a customized version of this file in the directory $HOME/.cime
, it will append to the file in $CIMEROOT/config/$model/machines/config_machines.xml
.
For an example of a config_machines.xml file for a linux cluster, look at $CIMEROOT/config/xml_schemas/config_machines_template.xml.
+cmake_macros
This subdirectory contains a hierarchy of cmake macros files which +are used to generate the flags to be used in the compilation of a +case. The cmake macro files are examined in the following order, with later files takeing precidence over earlier ones.
+universal.cmake
COMPILER.cmake
OS.cmake
MACHINE.cmake
COMPILER*_*OS.cmake
COMPILER*_*MACHINE.cmake
config_compilers.xml
DEPRECATED use cmake_macros
This file permits you to customize compiler settings for your machine and is appended to the file $CIMEROOT/config/$model/machines/config_compilers.xml.
+The following is an example of what would be needed for customized a ibm compiler flags on a BlueGeneQ machine.
+<?xml version="1.0" encoding="UTF-8"?>
+<config_compilers version="2.0">
+ <compiler COMPILER="ibm" OS="BGQ">
+ <FFLAGS> -g -qfullpath -qmaxmem=-1 -qspillsize=2500 -qextname=flush </FFLAGS>
+ <ADD_FFLAGS DEBUG="FALSE"> -O3 -qstrict -qinline=auto </ADD_FFLAGS>
+ <ADD_FFLAGS DEBUG="FALSE" compile_threaded="TRUE"> -qsmp=omp </ADD_FFLAGS>
+ <ADD_FFLAGS DEBUG="TRUE" compile_threaded="TRUE"> -qsmp=omp:noopt </ADD_FFLAGS>
+ <ADD_CPPDEFS> -DLINUX </ADD_CPPDEFS>
+ <CONFIG_ARGS> --build=powerpc-bgp-linux --host=powerpc64-suse-linux </CONFIG_ARGS>
+ <LDFLAGS> -Wl,--relax -Wl,--allow-multiple-definition </LDFLAGS>
+ </compiler>
+</config_compilers>
+
config_batch.xml
This file permits you to customize batch settings for you machine and is appended to the file $CIMEROOT/config/$model/machines/config_batch.xml.
+The following is an example of what would be needed to add batch settings for pbs on the machine brutus.
+<?xml version="1.0"?>
+<config_batch version="2.0">
+ <batch_system type="pbs" MACH="brutus" >
+ <directives>
+ <directive default="/bin/bash" > -S {{ shell }} </directive>
+ </directives>
+ <queues>
+ <queue walltimemax="00:59:00" nodemin="1" nodemax="624" default="true">batch</queue>
+ </queues>
+ </batch_system>
+</config_batch>
+
CIME provides the ability to define model specific config and hooks.
+The config alters CIME’s runtime and the hooks are triggered during their event.
+CIME will search cime_config/customize
and load any python found under this directory or it’s children.
Any variables, functions or classes loaded are available from the CIME.customize
module.
Available config and descriptions.
+Variable |
+Default |
+Type |
+Description |
+
---|---|---|---|
additional_archive_components |
+(‘drv’, ‘dart’) |
+tuple |
+Additional components to archive. |
+
allow_unsupported |
+True |
+bool |
+If set to True then unsupported compsets and resolutions are allowed. |
+
baseline_store_teststatus |
+True |
+bool |
+If set to True and GENERATE_BASELINE is set then a teststatus.log is created in the case’s baseline. |
+
build_cime_component_lib |
+True |
+bool |
+If set to True then Filepath, CIME_cppdefs and CCSM_cppdefs directories are copied from CASEBUILD directory to BUILDROOT in order to build CIME’s internal components. |
+
build_model_use_cmake |
+False |
+bool |
+If set to True the model is built using using CMake otherwise Make is used. |
+
calculate_mode_build_cost |
+False |
+bool |
+If set to True then the TestScheduler will set the number of processors for building the model to min(16, (($GMAKE_J * 2) / 3) + 1) otherwise it’s set to 4. |
+
case_setup_generate_namelist |
+False |
+bool |
+If set to True and case is a test then namelists are created during case.setup. |
+
check_invalid_args |
+True |
+bool |
+If set to True then script arguments are checked for being valid. |
+
check_machine_name_from_test_name |
+True |
+bool |
+If set to True then the TestScheduler will use testlists to parse for a list of tests. |
+
common_sharedlibroot |
+True |
+bool |
+If set to True then SHAREDLIBROOT is set for the case and SystemTests will only build the shared libs once. |
+
copy_cesm_tools |
+True |
+bool |
+If set to True then CESM specific tools are copied into the case directory. |
+
copy_cism_source_mods |
+True |
+bool |
+If set to True then $CASEROOT/SourceMods/src.cism/source_cism is created and a README is written to directory. |
+
copy_e3sm_tools |
+False |
+bool |
+If set to True then E3SM specific tools are copied into the case directory. |
+
create_bless_log |
+False |
+bool |
+If set to True and comparing test to baselines the most recent bless is added to comments. |
+
create_test_flag_mode |
+cesm |
+str |
+Sets the flag mode for the create_test script. When set to cesm, the -c flag will compare baselines against a give directory. |
+
default_short_term_archiving |
+True |
+bool |
+If set to True and the case is not a test then DOUT_S is set to True and TIMER_LEVEL is set to 4. |
+
driver_choices |
+(‘mct’, ‘nuopc’) |
+tuple |
+Sets the available driver choices for the model. |
+
driver_default |
+nuopc |
+str |
+Sets the default driver for the model. |
+
enable_smp |
+True |
+bool |
+If set to True then SMP= is added to model compile command. |
+
make_case_run_batch_script |
+False |
+bool |
+If set to True and case is not a test then case.run.sh is created in case directory from $MACHDIR/template.case.run.sh. |
+
mct_path |
+{srcroot}/libraries/mct |
+str |
+Sets the path to the mct library. |
+
serialize_sharedlib_builds |
+True |
+bool |
+If set to True then the TestScheduler will use proc_pool + 1 processors to build shared libraries otherwise a single processor is used. |
+
set_comp_root_dir_cpl |
+True |
+bool |
+If set to True then COMP_ROOT_DIR_CPL is set for the case. |
+
share_exes |
+False |
+bool |
+If set to True then the TestScheduler will share exes between tests. |
+
shared_clm_component |
+True |
+bool |
+If set to True and then the clm land component is built as a shared lib. |
+
sort_tests |
+False |
+bool |
+If set to True then the TestScheduler will sort tests by runtime. |
+
test_custom_project_machine |
+melvin |
+str |
+Sets the machine name to use when testing a machine with no PROJECT. |
+
test_mode |
+cesm |
+str |
+Sets the testing mode, this changes various configuration for CIME’s unit and system tests. |
+
ufs_alternative_config |
+False |
+bool |
+If set to True and UFS_DRIVER is set to nems then model config dir is set to $CIMEROOT/../src/model/NEMS/cime/cime_config. |
+
use_kokkos |
+False |
+bool |
+If set to True and CAM_TARGET is preqx_kokkos, theta-l or theta-l_kokkos then kokkos is built with the shared libs. |
+
use_nems_comp_root_dir |
+False |
+bool |
+If set to True then COMP_ROOT_DIR_CPL is set using UFS_DRIVER if defined. |
+
use_testreporter_template |
+True |
+bool |
+If set to True then the TestScheduler will create testreporter in $CIME_OUTPUT_ROOT. |
+
verbose_run_phase |
+False |
+bool |
+If set to True then after a SystemTests successful run phase the elapsed time is recorded to BASELINE_ROOT, on a failure the test is checked against the previous run and potential breaking merges are listed in the testlog. |
+
xml_component_key |
+COMP_ROOT_DIR_{} |
+str |
+The string template used as the key to query the XML system to find a components root directory e.g. the template COMP_ROOT_DIR_{} and component LND becomes COMP_ROOT_DIR_LND. |
+
Available hooks and descriptions.
+Function |
+Description |
+
---|---|
|
+Called after the model is built. |
+
|
+Called before the model is run. |
+
|
+Called after the model is run. |
+
If you use CIME as part of a climate model or standalone, the content of the cime directory is the same.
+If you are using it as part of a climate model, cime is usually one of the first subdirectories under the main directory.
+Directory or Filename |
+Description |
+
---|---|
README, etc. |
+typical top-level directory content |
+
components/ |
+source code for active models |
+
cime/ |
+All of CIME code |
+
CIME’s content is split into several subdirectories. Users should start in the scripts/ subdirectory.
+Directory or Filename |
+Description |
+
---|---|
CIME/ |
+The main CIME source |
+
CIME/ParamGen |
+Python tool for generating runtime params |
+
CIME/Servers |
+Scripts to interact with input data servers |
+
CIME/SystemTests |
+Scripts for create_test tests. |
+
CIME/Tools |
+Auxillary tools, scripts and functions. |
+
CMakeLists.txt |
+For building with CMake |
+
CONTRIBUTING.md |
+Guide for contributing to CIME |
+
ChangeLog |
+Developer-maintained record of changes to CIME |
+
ChangeLog_template |
+Template for an entry in ChangeLog |
+
LICENSE.TXT |
+The CIME license |
+
MANIFEST.in |
++ |
README.md |
+README in markdown language |
+
conftest.py |
++ |
doc |
+Documentation for CIME in rst format |
+
docker |
+Container for CIME testing |
+
scripts/ |
+The CIME user interface |
+
tools/ |
+Standalone climate modeling tools |
+
utils/ |
+Some Perl source code needed by some prognostic components |
+
The file $CIMEROOT/config/[cesm,e3sm]/config_files.xml contains all model-specific information that CIME uses to determine compsets, compset component settings, model grids, machines, batch queue settings, and compiler settings. It contains the following xml nodes, which are discussed below or in subsequent sections of this guide.
+compset definitions:
+ <entry id="COMPSETS_SPEC_FILE">
+
+component specific compset settings:
+ <entry id="CONFIG_CPL_FILE">
+ <entry id="CONFIG_CPL_FILE_MODEL_SPECIFIC">
+ <entry id="CONFIG_ATM_FILE">
+ <entry id="CONFIG_LND_FILE">
+ <entry id="CONFIG_ROF_FILE">
+ <entry id="CONFIG_ICE_FILE">
+ <entry id="CONFIG_OCN_FILE">
+ <entry id="CONFIG_GLC_FILE">
+ <entry id="CONFIG_WAV_FILE">
+ <entry id="CONFIG_ESP_FILE">
+
+pe-settings:
+ <entry id="PES_SPEC_FILE">
+
+grid definitions:
+ <entry id="GRIDS_SPEC_FILE">
+
+machine specific definitions:
+ <entry id="MACHINES_SPEC_FILE">
+ <entry id="BATCH_SPEC_FILE">
+ <entry id="COMPILERS_SPEC_FILE">
+ <entry id="PIO_SPEC_FILE">
+
+testing:
+ <entry id="CONFIG_TESTS_FILE">
+ <entry id="TESTS_SPEC_FILE">
+ <entry id="TESTS_MODS_DIR">
+ <entry id="SYSTEM_TESTS_DIR">
+
+archiving:
+ <entry id="LTARCHIVE_SPEC_FILE">
+
+CIME components namelists definitions:
+ <entry id="NAMELIST_DEFINITION_FILE">
+
+user-mods directories:
+ <entry id="USER_MODS_DIR">
+
If you have access to a run that you want to clone, the +create_clone command will create a new case and run case.setup +while preserving local modifications to the case.
+Here is a simple example:
+> cd $CIMEROOT/scripts
+> create_clone --case $CASEROOT --clone $CLONEROOT
+> cd $CASEROOT
+> case.build
+> case.submit
+
The create_clone script preserves any local namelist modifications +made in the user_nl_xxxx files as well as any source code +modifications in the SourceMods/ directory tree. Otherwise, your $CASEROOT directory +directory will appear as if create_newcase had just been run.
+Important: Do not change anything in the env_case.xml file.
+See the help text for more usage information.
+> create_clone --help
+
create_clone has several useful optional arguments. To point to +the executable of the original case you are cloning from.
+> create_clone --case $CASEROOT --clone $CLONEROOT --keepexe
+> cd $CASEROOT
+> case.submit
+
If the --keepexe
optional argument is used, then no SourceMods
+will be permitted in the cloned directory. A link will be made when
+the cloned case is created pointing the cloned SourceMods/ directory
+to the original case SourceMods directory.
Warning
+No changes should be made to env_build.xml
or env_mach_pes.xml
in the cloned directory.
shell_commands
and user_nl_xxx
files in a user_mods directory by calling:
> create_clone --case $CASEROOT --clone $CLONEROOT --user-mods-dir USER_MODS_DIR [--keepexe]
+
Note that an optional --keepexe
flag can also be used in this case.
Warning
+If there is a shell_commands
file, it should not have any changes to xml variables in either env_build.xml
or env_mach_pes.xml
.
Another approach to duplicating a case is to use the information in +the case’s README.case and CaseStatus files to create a new +case and duplicate the relevant xmlchange commands that were +issued in the original case. This alternative will not preserve any +local modifications that were made to the original case, such as +source-code or build-script revisions; you will need to import those +changes manually.
+In CIME, multiple components can define compsets that are targeted to their model development needs.
+Each component supports a set of compset longnames that are used in testing and supported in out of the box configurations.
+To determine if the compset name to create_newcase is a supported component, CIME looks in the config_files.xml file and parses the
+the xml element COMPSETS_SPEC_FILE
in order to determine which component is defining the compset.
In the case of CESM, this xml element has the contents shown here, where $SRCROOT
is the root of your CESM sandbox and contains $CIMEROOT
as a subdirectory:
<entry id="COMPSETS_SPEC_FILE">
+ <type>char</type>
+ <default_value>unset</default_value>
+ <values>
+ <value component="allactive">$SRCROOT/cime_config/config_compsets.xml</value>
+ <value component="drv" >$CIMEROOT/src/drivers/mct/cime_config/config_compsets.xml</value>
+ <value component="cam" >$SRCROOT/components/cam/cime_config/config_compsets.xml</value>
+ <value component="cism" >$SRCROOT/components/cism/cime_config/config_compsets.xml</value>
+ <value component="clm" >$SRCROOT/components/clm/cime_config/config_compsets.xml</value>
+ <value component="cice" >$SRCROOT/components/cice/cime_config/config_compsets.xml</value>
+ <value component="pop" >$SRCROOT/components/pop/cime_config/config_compsets.xml</value>
+ </values>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>file containing specification of all compsets for primary component (for documentation only - DO NOT EDIT)</desc>
+ <schema>$CIMEROOT/config/xml_schemas/config_compsets.xsd</schema>
+</entry>
+
Every file listed in COMPSETS_SPEC_FILE will be searched for the compset specified in the call to create_newcase.
+CIME will note which component’s config_compsets.xml had the matching compset name and that component will be treated as
+the primary component As an example, the primary component for a compset that has a prognostic atmosphere,
+land and cice (in prescribed mode) and a data ocean is the atmosphere component (for cesm this is CAM) because the compset
+is defined, using the above example, in $SRCROOT/components/cam/cime_config/config_compsets.xml
+In a compset where all components are prognostic, the primary component will be allactive.
Each config_compsets.xml file has a list of allowed component sets in the form of a longname and an alias.
+A compset longname has this form:
+TIME_ATM[%phys]_LND[%phys]_ICE[%phys]_OCN[%phys]_ROF[%phys]_GLC[%phys]_WAV[%phys]_ESP[_BGC%phys]
+
Supported values for each element of the longname:
+TIME = model time period (e.g. 1850, 2000, 20TR, SSP585...)
+
+CIME supports the following values for ATM,LND,ICE,OCN,ROF,GLC,WAV and ESP.
+ATM = [DATM, SATM, XATM]
+LND = [DLND, SLND, XLND]
+ICE = [DICE, SICE, SICE]
+OCN = [DOCN, SOCN, XOCN]
+ROF = [DROF, SROF, XROF]
+GLC = [SGLC, XGLC]
+WAV = [SWAV, XWAV]
+ESP = [SESP]
+
A CIME-driven model may have other options available. Use query_config to determine the available options.
+The OPTIONAL %phys attributes specify sub-modes of the given system. +For example, DOCN%DOM is the DOCN data ocean (rather than slab-ocean) mode. +All the possible %phys choices for each component are listed by calling query_config –compsets. +All data models have a %phys option that corresponds to the data model mode.
+Every model component also contains a config_component.xml file that has two functions:
+Specifying the component-specific definitions of what can appear after the %
in the compset longname, (for example, DOM
in DOCN%DOM
).
Specifying the compset-specific $CASEROOT
xml variables.
CIME first parses the following nodes to identify appropriate config_component.xml files for the driver. There are two such files; one is model-independent and the other is model-specific.
+<entry id="CONFIG_CPL_FILE">
+ ...
+ <default_value>$CIMEROOT/driver_cpl/cime_config/config_component.xml</default_value>
+ ..
+ </entry>
+
+ <entry id="CONFIG_CPL_FILE_MODEL_SPECIFIC">
+ <default_value>$CIMEROOT/driver_cpl/cime_config/config_component_$MODEL.xml</default_value>
+ </entry>
+
CIME then parses each of the nodes listed below, using using the value of the component attribute to determine which xml files to use for the requested compset longname.
+<entry id="CONFIG_ATM_FILE">
+<entry id="CONFIG_ESP_FILE">
+<entry id="CONFIG_ICE_FILE">
+<entry id="CONFIG_GLC_FILE">
+<entry id="CONFIG_LND_FILE">
+<entry id="CONFIG_OCN_FILE">
+<entry id="CONFIG_ROF_FILE">
+<entry id="CONFIG_WAV_FILE">
+
As an example, the possible atmosphere components for CESM have the following associated xml files.
+<entry id="CONFIG_ATM_FILE">
+ <type>char</type>
+ <default_value>unset</default_value>
+ <values>
+ <value component="cam" >$SRCROOT/components/cam/cime_config/config_component.xml</value>
+ <value component="datm">$CIMEROOT/components/data_comps/datm/cime_config/config_component.xml</value>
+ <value component="satm">$CIMEROOT/components/stub_comps/satm/cime_config/config_component.xml</value>
+ <value component="xatm">$CIMEROOT/components/xcpl_comps/xatm/cime_config/config_component.xml</value>
+ </values>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>file containing specification of component specific definitions and values(for documentation only - DO NOT EDIT)</desc>
+ <schema>$CIMEROOT/cime_config/xml_schemas/entry_id.xsd</schema>
+</entry>
+
If the compset’s atm component attribute is datm
, the file $CIMEROOT/components/data_comps/datm/cime_config/config_component.xml
specifies all possible component settings for DATM
.
The schema for every config_component.xml file has a <description>
node that specifies all possible values that can follow the %
character in the compset name.
To list the possible values, use the query_config –component datm command.
+A description of how CIME interprets a compset name is given in the section Compset longname .
+To create a new compset, you will at a minimum have to:
+edit the approprite config_components.xml
file(s) to add your new requirements
edit associate namelist_definitions_xxx.xml
in the associated cime_config
directories.
+(e.g. if a change is made to the the config_components.xml
for DOCN
then namelist_definitions_docn.xml
file will also need to be modified).
It is important to point out, that you will need expertise in the target component(s) you are trying to modify in order to add new compset functionality for that particular component. +We provide a few examples below that outline this process for a few simple cases.
+Say you want to add a new mode, FOO
, to the data ocean model, DOCN
. Lets call this mode, FOO
.
+This would imply when parsing the compset longname, CIME would need to be able to recognize the string _DOCN%FOO_
.
+To enable this, you will need to do the following:
edit $CIMEROOT/src/components/data_comps/docn/cime_config/config_component.xml
(see the FOO
additions below).
add an entry to the <description modifier block="1">
block as shown below
<description modifier_mode="1">
+ <desc ocn="DOCN...[%FOO]">DOCN </desc>
+ ...
+ <desc option="FOO"> new mode</desc>
+ ....
+</description>
+
add an entry to the <entry id="DOCN_MODE">
block as shown below:
<entry id="DOCN_MODE">
+ ....
+ <values match="last">
+ ....
+ <value compset="_DOCN%FOO_" >prescribed</value>
+ ...
+</entry>
+
modify any of the other xml entries that need a new dependence on FOO
edit $CIMEROOT/src/components/data_comps/docn/cime_config/namelist_definition_docn.xml
(see the FOO
additions below).
add an entry to the datamode
block as shown below.
<entry id="datamode">
+ ....
+ <valid_values>...FOO</valid_values>
+ ...
+</entry>
+
add additional changes to namelist_definition_docn.xml
for the new mode
Todo
+Add additional examples for creating a case
+This and following sections provide more detail about the basic commands of the CIME Case Control System: create_newcase, +case.setup, case.build and case.submit. On a supported system, you can configure, build and run many complex +climate model configurations with only these 4 commands.
+To see if your machine is supported try:
+> query_config --machines
+
If you are not on an out-of-the box CIME-supported platform, you will need to port CIME to your system before proceeding.
+The first step in creating a CIME-based experiment is to use create_newcase.
+See the options for create_newcase in the help text.:
+> create_newcase --help
+
The only required arguments to create_newcase are:
+> create_newcase --case CASENAME --compset COMPSET --res GRID
+
Creating a CIME experiment or case requires, at a minimum, specifying a compset and a model grid and a case directory. +CIME supports out-of-the-box component sets, model grids and hardware platforms (machines).
+Warning
+The --case
argument must be a string and may not contain any of the following special characters
> + * ? < > { } [ ] ~ ` @ :
+
The --case
argument is used to define the name of your case, a very important piece of
+metadata that will be used in filenames, internal metadata and directory paths. The
+CASEROOT
is a directory create_newcase will create with the same name as the
+CASENAME
. If CASENAME
is simply a name (not a path), CASEROOT
is created in
+the directory where you execute create_newcase. If CASENAME
is a relative or absolute
+path, CASEROOT
is created there, and the name of the case will be the last component
+of the path.
Suppose create_newcase was called as follows. +Here, $CIMEROOT is the full pathname of the root directory of the CIME distribution:
+> cd $CIMEROOT/scripts
+> create_newcase --case ~/cime/example1 --compset A --res f09_g16_rx1
+
In the example, the command creates a $CASEROOT
directory: ~/cime/example1
.
+If that directory already exists, a warning is printed and the command aborts.
In the argument to --case
, the case name is taken from the string after the last slash
+— so here the case name is example1
.
The output from create_newcase includes information such as.
+The compset longname is 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_SWAV
The grid set is a%0.9x1.25_l%0.9x1.25_oi%gx1v6_r%r05_m%gx1v6_g%null_w%null
create_newcase installs files in $CASEROOT
that will build and run the model and to optionally archive the case on the target platform.
Running create_newcase creates the following scripts, files and directories in $CASEROOT
:
User Scripts
+Script to build component and utility libraries and model executable.
+Script to perform namelist baseline operations (compare, generate, or both).”
+Script to query the queue on any queue system.
+Script used to set up the case (create the case.run script, Macros file and user_nl_xxx files).
+Script to submit the case to run using the machine’s batch queueing system.
+Script to verify case is set up correctly.
+Script for checking for various input data sets and moving them into place.
+Script to query and modify the NTASKS, ROOTPE, and NTHRDS for each component model.
+Script for users to see their component namelists in $CASEROOT/CaseDocs
before running the model.
Script for users to see batch submit and mpirun command.”
+Script to modify values in the xml files.
+Script to query values in the xml files.
+XML Files
+Defines patterns of files to be sent to the short-term archive. +You can edit this file at any time. You CANNOT use xmlchange to modify variables in this file.”
+Sets batch system settings such as wallclock time and queue name.”
+Sets model build settings. This includes component resolutions and component compile-time configuration options. +You must run the case.build command after changing this file.
+Parameters set by create_newcase
+Sets component machine-specific processor layout (see changing pe layout ). +The settings in this are critical to a well-load-balanced simulation (see load balancing).
+Sets a number of machine-specific environment variables for building and/or running. +You CANNOT use xmlchange to modify variables in this file.
+Sets runtime settings such as length of run, frequency of restarts, output of coupler diagnostics, and short-term and long-term archiving. +This file can be edited at any time before a job starts.
+Sets paramateres for the runtime workflow.
+User Source Mods Directory
+Top-level directory containing subdirectories for each compset component where you can place modified source code for that component. +You may also place modified buildnml and buildlib scripts here.”
+Provenance
+File detailing create_newcase usage. +This is a good place to keep track of runtime problems and changes.”
+File containing a list of operations done in the current case.
+Non-modifiable work directories
+Work directory containing scripts to generate component namelists and component and utility libraries (PIO or MCT, for example). You should never have to edit the contents of this directory.
+Work directory that holds copies of files that should not be changed. Certain xml files are locked after their variables have been used by should no longer be changed (see below).
+Work directory containing support utility scripts. You should never need to edit the contents of this directory.”
+The $CASEROOT
xml files are organized so that variables can be
+locked at certain points after they have been resolved (used) in other
+parts of the scripts system.
CIME does this by locking a file in $CASEROOT/LockedFiles
and
+not permitting you to modify that file unless, depending on the file,
+you call case.setup –clean or
+case.build –clean .
CIME locks your $CASEROOT
files according to the following rules:
The env_case.xml file can never be unlocked.
+To unlock env_mach_pes.xml, run case.setup –clean.
+To unlock env_build.xml, run case.build –clean
+Variables in env_run.xml, env_batch.xml and env_archive.xml are never locked, and most can be changed at any time.
There are some exceptions in the env_batch.xml file.
A user may want to customize a target case with a combination of
+user_nl_xxx
file modifications and/or SourceMods
for some
+components and/or xmlchange commands. As an example, the user
+might want to carry out a series of experiments based on a common set
+of changes to the namelists, source code and/or case xml settings.
+Rather than make these changes each time a new experimental
+CASEROOT
is generated, the user can create a directory on local
+disk with a set of changes that will be applied to each case.
As an example, the directory could contain the following files:
+> user_nl_cpl
+> shell_commands (this would contain ./xmlchange commands)
+> SourceMods/src.cam/dyncomp.F90
+
It is important to note that the file containing the xmlchange
+commands must be named shell_commands
in order for it to be recognised
+and run upon case creation.
The structure of the component directories do not need to be the
+same as in the component source code. As an example, should the user
+want to modify the src/dynamics/eul/dyncomp.F90
file within the
+CAM source code, the modified file should be put into the directory
+SourceMods/src.cam
directly. There is no need to mimic the source
+code structure, such as SourceMods/src.cam/dynamics/eul
.
When the user calls create_newcase with the --user-mods-dir
pointing to the
+full pathname of the directory containing these changes, then the CASEROOT
will be
+created with these changes applied.
CIME looks at the xml node GRIDS_SPEC_FILE
in $CIMEROOT/config/$models/config_files.xml file to identify supported out-of-the-box model grids for the target model.
The node has the following contents:
+<entry id="GRIDS_SPEC_FILE">
+ <type>char</type>
+ <default_value>$CIMEROOT/cime_config/$MODEL/config_grids.xml</default_value>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>file containing specification of all supported model grids, domains and mapping files (for documentation only - DO NOT EDIT)</desc>
+ <schema>$CIMEROOT/cime_config/xml_schemas/config_grids_v2.xsd</schema>
+</entry>
+
CIME model grids generally are associated with a specific combination of atmosphere, land, land-ice, river-runoff and ocean/ice grids. The naming convention for these grids uses only atmosphere, land, and ocean/ice grid specifications.
+A model grid longname has the form:
+a%name_l%name_oi%name_r%name_m%mask_g%name_w%name
+
For reference:
+a% = atmosphere grid
+l% = land grid
+oi% = ocean/sea-ice grid (must be the same)
+r% = river grid
+m% = ocean mask grid
+g% = internal land-ice grid
+w% = wave component grid
+
The ocean mask grid determines land/ocean boundaries in the model. +On the ocean grid, a grid cell is assumed to be either all ocean or all land. +The land mask on the land grid is obtained by mapping the ocean mask +(using first-order conservative mapping) from the ocean grid to the land grid.
+From the point of view of model coupling, the glc grid is assumed to +be identical to the land grid. The internal land-ice grid can be different, +however, and is specified by the g% value.
+As an example, examine this actual grid longname:
+a%ne30np4_l%ne30np4_oi%gx1v7_r%r05_m%gx1v7_g%null_w%null
+
It refers to a model grid with a ne30np4 spectral element (approximately 1-degree) atmosphere and land grids, gx1v7 Greenland pole, 1-degree ocean and sea-ice grids, a 1/2 degree river routing grid, null wave and internal cism grids, and an gx1v7 ocean mask. +The alias for this grid is ne30_g16.
+CIME also permits users to introduce their own user-defined grids.
+Component grids are denoted by the following naming convention:
+“[dlat]x[dlon]” are regular lon/lat finite volume grids where dlat and dlon are the approximate grid spacing. The shorthand convention is “fnn” where nn generally is a pair of numbers indicating the resolution. An example is 1.9x2.5 or f19 for the approximately “2-degree” finite-volume grid. Note that CAM uses an [nlat]x[nlon] naming convention internally for this grid.
“Tnn” are spectral lon/lat grids where nn is the spectral truncation value for the resolution. The shorthand name is identical. Example: T85.
“ne[X]np[Y]” are cubed sphere resolutions where X and Y are integers. The short name generally is ne[X]. Examples: ne30np4 or ne30.
“pt1” is a single grid point.
“gx[D]v[n]” is a POP displaced pole grid where D is the approximate resolution in degrees and n is the grid version. The short name generally is g[D][n]. An example is gx1v7 or g17 for a grid of approximately 1-degree resolution.
“tx[D]v[n]” is a POP tripole grid where D is the approximate resolution in degrees and n is the grid version.
“oRSS[x]to[y]” is an MPAS grid with grid spacing from x to y kilometers.
“oEC[x]to[y]” is an MPAS grid with grid spacing from x to y kilometers.
> query_config --grids
+
The most common resolutions have the atmosphere and land components on one grid and the ocean and ice on a second grid. The following overview assumes that this is the case. +The naming convention looks like f19_g17, where the f19 indicates that the atmosphere and land are on the 1.9x2.5 (finite volume dycore) grid while the g17 means the ocean and ice are on the gx1v6 one-degree displaced pole grid.
+CIME enables users to add their own component grid combinations. +The steps for adding a new component grid to the model system follow. This process can be simplified if the atmosphere and land are running on the same grid.
+The first step is to generate SCRIP grid files for the atmosphere, land, ocean, land-ice, river and wave component grids that will comprise your model grid. +If you are introducing just one new grid, you can leverage SCRIP grid files that are already in place for the other components. +There is no supported functionality for creating the SCRIP format file.
Build the check_map utility by following the instructions in $CIMEROOT/tools/mapping/check_maps/INSTALL. Also confirm that the ESMF toolkit is installed on your machine.
+When you add new user-defined grid files, you also need to generate a set of mapping files so the coupler can send data from a component on one grid to a component on another grid. +There is an ESMF tool that tests the mapping file by comparing a mapping of a smooth function to its true value on the destination grid. +We have tweaked this utility to test a suite of smooth functions, as well as ensure conservation (when the map is conservative). +Before generating mapping functions it is highly recommended that you build this utility.
+Generate these mapping files:
+atm <-> ocn
+atm <-> wav
+lnd <-> rof
+lnd <-> glc
+ocn <-> wav
+rof -> ocn
+
++Using the SCRIP grid files from Step 1, generate a set of conservative (area-averaged) and non-conservative (patch and bilinear) mapping files.
+You can do this by calling gen_cesm_maps.sh in
+$CIMEROOT/tools/mapping/gen_mapping_files/
. +This script generates all the mapping files needed exceptrof -> ocn
, which is discussed below. +This script uses the ESMF offline weight generation utility, which you must build prior to running gen_cesm_maps.sh.+
+- The README file in the gen_mapping_files/ directory describes how to run gen_cesm_maps.sh. The basic usage is shown here:
- +
++> cd $CIMEROOT/tools/mapping/gen_mapping_files +> ./gen_cesm_maps.sh \ + --fileocn <input SCRIP ocn_grid full pathname> \ + --fileatm <input SCRIP atm grid full pathname> \ + --filelnd <input SCRIP lnd grid full pathname> \ + --filertm <input SCRIP rtm grid full pathname> \ + --nameocn <ocnname in output mapping file> \ + --nameatm <atmname in output mapping file> \ + --namelnd <lndname in output mapping file> \ + --namertm <rtmname in output mapping file> +- This command generates the following mapping files:
- +
++map_atmname_TO_ocnname_aave.yymmdd.nc +map_atmname_TO_ocnname_blin.yymmdd.nc +map_atmname_TO_ocnname_patc.yymmdd.nc +map_ocnname_TO_atmname_aave.yymmdd.nc +map_ocnname_TO_atmname_blin.yymmdd.nc +map_atmname_TO_lndname_aave.yymmdd.nc +map_atmname_TO_lndname_blin.yymmdd.nc +map_lndname_TO_atmname_aave.yymmdd.nc +map_ocnname_TO_lndname_aave.yymmdd.nc +map_lndname_TO_rtmname_aave.yymmdd.nc +map_rtmname_TO_lndname_aave.yymmdd.nc +++Note
+You do not need to specify all four grids. For example, if you are running with the atmosphere and land on the same grid, then you do not need to specify the land grid (and atm<->rtm maps will be generated). +If you also omit the runoff grid, then only the 5 atm<->ocn maps will be generated.
+++Note
+ESMF_RegridWeightGen runs in parallel, and the
+gen_cesm_maps.sh
script has been written to run on yellowstone. +To run on any other machine, you may need to add some environment variables to$CIMEROOT/tools/mapping/gen_mapping_files/gen_ESMF_mapping_file/create_ESMF_map.sh
– search for hostname to see where to edit the file.
Generate atmosphere, land and ocean / ice domain files.
+Using the conservative ocean to land and ocean to atmosphere mapping files created in the previous step, you can create domain files for the atmosphere, land, and ocean; these are basically grid files with consistent masks and fractions. +You make these files by calling gen_domain in $CIMEROOT/tools/mapping/gen_domain_files. +The INSTALL file in the gen_domain_files/ directory describes how to build the gen_domain executable. The README file in the same directory explains how to use the tool. The basic usage is:
+> ./gen_domain -m ../gen_mapping_files/map_ocnname_TO_lndname_aave.yymmdd.nc -o ocnname -l lndname
+> ./gen_domain -m ../gen_mapping_files/map_ocnname_TO_atmname_aave.yymmdd.nc -o ocnname -l atmname
+
These commands generate the following domain files:
+domain.lnd.lndname_ocnname.yymmdd.nc
+domain.ocn.lndname_ocnname.yymmdd.nc
+domain.lnd.atmname_ocnname.yymmdd.nc
+domain.ocn.atmname_ocnname.yymmdd.nc
+domain.ocn.ocnname.yymmdd.nc
+
Note
+The input atmosphere grid is assumed to be unmasked (global). Land cells whose fraction is zero will have land mask = 0.
+Note
+If the ocean and land grids are identical then the mapping file will simply be unity and the land fraction will be one minus the ocean fraction.
+If you are adding a new ocn or rtm grid, create a new rtm->ocn mapping file. (Otherwise you can skip this step.) +The process for mapping from the runoff grid to the ocean grid is currently undergoing many changes. +At this time, if you are running with a new ocean or runoff grid, please contact Michael Levy (mlevy_AT_ucar_DOT_edu) for assistance. If you are running with standard ocean and runoff grids, the mapping file should already exist and you do not need to generate it.
CESM specific: If you are adding a new atmosphere grid, this means you are also generating a new land grid, and you will need to create a new CLM surface dataset. (Otherwise you can skip this step). +You need to first generate mapping files for CLM surface dataset (since this is a non-standard grid).
+ > cd $CIMEROOT/../components/clm/tools/mkmapdata
+ > ./mkmapdata.sh --gridfile <lnd SCRIP grid file> --res <atm resolution name> --gridtype global
+
+These mapping files are then used to generate CLM surface dataset. Below is an example for a current day surface dataset (model year 2000).
+
+::
+
+ > cd $CIMEROOT/../components/clm/tools/mksurfdata_map
+ > ./mksurfdata.pl -res usrspec -usr_gname <atm resolution name> -usr_gdate yymmdd -y 2000
+
Create grid file needed for create_newcase.
+The next step is to add the necessary new entries in the appropriate config_grids.xml
file.
+You will need to modify $CIMEROOT/config/cesm/config_grids.xml
or $CIMEROOT/config/e3sm/config_grids.xml
depending on the value of $CIME_MODEL
.
+You will need to:
add a single <model_grid>
entry
add possibly multiple <domain>
entries for every new component grid that you have added
add possibly multiple <gridmap>
entries for all the new component combinations that require new mapping files
Test new grid.
+Below assume that the new grid is an atmosphere grid.
+Test the new grid with all data components.
+(write an example)
+Test the new grid with CAM(newgrid), CLM(newgrid), DOCN(gx1v6), DICE(gx1v6)
+(write an example)
+
Part 1 of this guide explains the basic commands in the CIME Case Control System +that are needed to get a model running.
+Part 1 of this guide assumes that CIME or a CIME-driven model and the necessary input files +have been installed on the computer you are using. If that is not the case, see Porting CIME.
+Other prerequisites:
+Familiarity with basic climate modeling concepts.
Familiarity with UNIX command line terminals and the UNIX development environment.
A correct version of the Python interpreter.
CIME’s commands are Python scripts and require a correct version of +the Python interpreter to be installed. The Python version must be +greater than 2.11. Determine which version you have +like this:
+> python --version
+
Consult your local documentation if you need to update your python version.
+The following key terms and concepts are ingrained in the CCS and used frequently in this documentation. +See the Glossary for a more complete list of terms.
+components
+++In CIME, a coupled earth system model is made up of components that interact through a coupler and are all controlled by a driver.
+In the current version of CIME, there are 7 physical components allowed. They are:
+++atmosphere, ocean, sea-ice, land surface, river, ice sheet, ocean waves
+Components are also referred to as “models”. The choice of 7 is partly historical and partly determined by the physics of the +Earth system: these 7 components +occupy physically distinct domains in the Earth system and/or require different numerical grids for solving.
+
component types
+++For each of the 7 physical components (models), there can be three different implementations in a CIME-driven coupled model.
+active: Solve a complex set of equations to describe the model’s behavior. Also called prognostic or full models. +These can be full General Circulation Models. Multiple active models might be available (for example POP and MPAS-ocean to represent the global ocean) but only one ocean or atmosphere model at a time can be used in a component set.
+data: For some climate problems, it is necessary to reduce feedbacks within the system by replacing an active model with a +version that sends and receives the same variables to and from other models, but with the values read from files rather +than computed from the equations. The values received are ignored. These active-model substitutes are called data models.
+stub: For some configurations, no data model is needed and one instead uses a stub version that simply occupies the +required place in the driver and does not send or receive any data. For example, if you are setting up an aqua-planet case +you would only need a stub for the land model.
+
component set or compset:
+++The particular combination of active, data and stub versions of the 7 components is referred to +as a component set or compset. The Case Control System allows one to define +several possible compsets and configure and run them on supported platforms. +Here is an example of a component set longname from E3SM for a fully coupled active case:
+
1850SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV
+
See Component Sets for more information. “GLC” originally meant “glacier model” and is now an ice-sheet model but the GLC letters have stuck.
+compset alias:
+++Typing a compset longname like the above can be exhausting so the CCS allows defining a shorter compset alias +which is a short string that substitutes for the longname. In E3SM, the above longname can be reffered to as “WCYCL1850”.
+
Note
+++Long ago, CESM established a convention for the first letter in a compset alias based +on the combination of active, data and stub components. +If you see mention of “B-case” or “F-case”, it comes from these conventions. +They pre-date the introduction of a wave model as an option.
+
A |
+All data models |
+
B |
+All models fully active with stub glc |
+
C |
+Active ocean with data atm, river and sea ice. stub lnd, glc |
+
D |
+Active sea ice with data atm, ocean (slab) and river. stub lnd, glc |
+
E |
+Active atm, lnd, sea-ice, river, data ocean (slab), stub glc |
+
F |
+Active atm, lnd, river, sea-ice (thermodynamics only), data ocean (fixed SST), stub glc |
+
G |
+Active ocean and sea ice, data atmosphere and river, stub lnd and glc |
+
H |
+Active ocean and sea ice, data atmosphere, stub lnd, river and glc |
+
I |
+Active land and river model, data atmosphere, stub ocn, sea-ice, glc |
+
IG |
+Active land, river and ice-sheet, data atmosphere, stub ocn, sea-ice |
+
S |
+All stub models (for testing only) |
+
X |
+All x-compsets (2D sine waves for each component except stub glc; for testing only) |
+
grid set:
+++Each active model must solve its equations on a numerical grid. CIME allows models within the system to have +different grids. The resulting set of all numerical grids is called the grid set or usually just the grid. Like +the compset longnamme, the CCS allows one to define an alias to represent a grid set. This alias is also referred to +as the grid or sometimes the resolution.
+
The machine is the computer you are using to run CIME and build and run the climate model. It could be a workstation +or a national supercomputer. The exact name of machine is typically the UNIX hostname but it could be any string. A machine +may have one more more versions of Fortran, C and C++ compilers that are needed to compile the model’s source code and CIME.
+To build and execute a CIME-enabled climate model, you have to make choices of compset, model grid, +machine and compiler. The collection of these choices, and any additional +customizations you may make, is called the case.
+Any case that can be defined by the coupled model’s CIME configuration files and built with only basic commands in the +CIME Case Control System is an “out-of-the-box” case. Since CIME and its configuration files are kept with +the model source code and version-controlled together, its possible to match supported out-of-the-box cases with specific +versions of the model source code, promoting reproducibility and provenance. An out-of-the-box case is also called a base case
+Before using any CCS commands, set the CIME_MODEL
environment variable. In bash, use export as shown and replace
+<model> with the appropriate text. Current possibilities are “e3sm” or “cesm.”
> export CIME_MODEL=<model>
+
There are a number of possible ways to set CIME variables. +For variables that can be set in more than one way, the order of precedence is:
+variable appears in a command line argument to a CIME command
variable is set as an environment variable
variable is set in $HOME/.cime/config
as explained further here.
variable is set in a $CASEROOT
xml file
To see an example of how a case is created, configured, built and run with CIME, execute the following commands. (This assumes that CIME has been ported to your current machine).
+> cd cime/scripts
+> ./create_newcase --case mycase --compset X --res f19_g16
+> cd mycase
+> ./case.setup
+> ./case.build
+> ./case.submit
+
The output from each command is explained in the following sections.
+After you submit the case, you can follow the progress of your run by monitoring the CaseStatus file.
+> tail CaseStatus
+
Repeat the command until you see the message case.run success
.
Your CIME-driven model likely has many compset and gridset aliases defined for cases that are widely used by the +model developers.
+Use the utility query_config to see which out-of-the-box compsets, components, grids and machines are available for your model.
+To see lists of available compsets, components, grids and machines, look at the help text:
+> query_config --help
+
To see all available component sets, try:
+> query_config --compsets all
+
Usage examples
+To run query_config for compset information, follow this example, where drv is the component name:
+> query_config --compsets drv
+
The output will be similar to this:
+ --------------------------------------
+ Compset Short Name: Compset Long Name
+ --------------------------------------
+A : 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_SWAV
+ADWAV : 2000_SATM_SLND_SICE_SOCN_SROF_SGLC_DWAV%CLIMO
+S : 2000_SATM_SLND_SICE_SOCN_SROF_SGLC_SWAV_SESP
+ADLND : 2000_SATM_DLND%SCPL_SICE_SOCN_SROF_SGLC_SWAV
+ADESP_TEST : 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_SWAV_DESP%TEST
+X : 2000_XATM_XLND_XICE_XOCN_XROF_XGLC_XWAV
+ADESP : 2000_DATM%NYF_SLND_DICE%SSMI_DOCN%DOM_DROF%NYF_SGLC_SWAV_DESP
+AIAF : 2000_DATM%IAF_SLND_DICE%IAF_DOCN%IAF_DROF%IAF_SGLC_SWAV
+
Each model component specifies its own definitions of what can appear after the % modifier in the compset longname (for example, DOM in DOCN%DOM).
+To see what supported modifiers are for DOCN, run query_config as in this example:
+> query_config --component docn
+
The output will be similar to this:
+=========================================
+DOCN naming conventions
+=========================================
+
+ _DOCN%AQP1 : docn prescribed aquaplanet sst - option 1
+ _DOCN%AQP10 : docn prescribed aquaplanet sst - option 10
+ _DOCN%AQP2 : docn prescribed aquaplanet sst - option 2
+ _DOCN%AQP3 : docn prescribed aquaplanet sst - option 3
+ _DOCN%AQP4 : docn prescribed aquaplanet sst - option 4
+ _DOCN%AQP5 : docn prescribed aquaplanet sst - option 5
+ _DOCN%AQP6 : docn prescribed aquaplanet sst - option 6
+ _DOCN%AQP7 : docn prescribed aquaplanet sst - option 7
+ _DOCN%AQP8 : docn prescribed aquaplanet sst - option 8
+ _DOCN%AQP9 : docn prescribed aquaplanet sst - option 9
+ _DOCN%DOM : docn prescribed ocean mode
+ _DOCN%IAF : docn interannual mode
+ _DOCN%NULL : docn null mode
+ _DOCN%SOM : docn slab ocean mode
+ _DOCN%SOMAQP : docn aquaplanet slab ocean mode
+ _DOCN%SST_AQUAP : docn aquaplanet mode:
+
For more details on how CIME determines the output for query_config, see Component Sets.
+CIME looks at the xml node MACHINE_SPEC_FILE
in the config_files.xml file to identify supported out-of-the-box machines for the target model. The node has the following contents:
<entry id="MACHINES_SPEC_FILE">
+ <type>char</type>
+ <default_value>$CIMEROOT/cime_config/$MODEL/machines/config_machines.xml</default_value>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>file containing machine specifications for target model primary component (for documentation only - DO NOT EDIT)</desc>
+ <schema>$CIMEROOT/cime_config/xml_schemas/config_machines.xsd</schema>
+</entry>
+
You can supplement what is in the MACHINES_SPEC_FILE by adding a config_machines.xml file to your CIME config directory.
+Each <machine>
tag requires the following input:
DESC
: a text description of the machine
NODENAME_REGEX
: a regular expression used to identify the machine. It must work on compute nodes as well as login nodes.
+| Use the machine
option for create_test or create_newcase if this flag is not available.
OS
: the machine’s operating system
PROXY
: optional http proxy for access to the internet
COMPILERS
: compilers supported on the machine, in comma-separated list, default first
MPILIBS
: mpilibs supported on the machine, in comma-separated list, default first
PROJECT
: a project or account number used for batch jobs; can be overridden in environment or in $HOME/.cime/config
SAVE_TIMING_DIR
: (E3SM only) target directory for archiving timing output
SAVE_TIMING_DIR_PROJECTS
: (E3SM only) projects whose jobs archive timing output
CIME_OUTPUT_ROOT
: Base directory for case output; the bld and run directories are written below here
DIN_LOC_ROOT
: location of the input data directory
DIN_LOC_ROOT_CLMFORC
: optional input location for clm forcing data
DOUT_S_ROOT
: root directory of short-term archive files
DOUT_L_MSROOT
: root directory on mass store system for long-term archive files
BASELINE_ROOT
: root directory for system test baseline files
CCSM_CPRNC
: location of the cprnc tool, which compares model output in testing
GMAKE
: gnu-compatible make tool; default is “gmake”
GMAKE_J
: optional number of threads to pass to the gmake flag
TESTS
: (E3SM only) list of tests to run on the machine
BATCH_SYSTEM
: batch system used on this machine (none is okay)
SUPPORTED_BY
: contact information for support for this system
MAX_TASKS_PER_NODE
: maximum number of threads/tasks per shared memory node on the machine
MAX_MPITASKS_PER_NODE
: number of physical PES per shared node on the machine. In practice the MPI tasks per node will not exceed this value.
PROJECT_REQUIRED
: Does this machine require a project to be specified to the batch system?
mpirun
: The mpi exec to start a job on this machine.
+This is itself an element that has sub-elements that must be filled:
Must have a required <executable>
element
May have optional attributes of compiler
, mpilib
and/or threaded
May have an optional <arguments>
element which in turn contains one or more <arg>
elements.
+These specify the arguments to the mpi executable and are dependent on your mpi library implementation.
May have an optional <run_exe>
element which overrides the default_run_exe
May have an optional <run_misc_suffix>
element which overrides the default_run_misc_suffix
May have an optional <aprun_mode>
element which controls how CIME generates arguments when <executable>
contains aprun
.
The <aprun_mode>
element can be one of the following. The default value is ignore
.
ignore
will cause CIME to ignore it’s aprun module and join the values found in <arguments>
.
default
will use CIME’s aprun module to generate arguments.
override
behaves the same as default
expect it will use <arguments>
to mutate the generated arguments. When using this mode a position
attribute can be placed on <arg>
tags to specify how it’s used.
The position
attribute on <arg>
can take one of the following values. The default value is per
.
global
causes the value of the <arg>
element to be used as a global argument for aprun
.
per
causes the value of the <arg>
element to be appended to each separate binaries arguments.
Example using override
:
<executable>aprun</executable>
+<aprun_mode>override</aprun_mode>
+<arguments>
+ <arg position="global">-e DEBUG=true</arg>
+ <arg>-j 20</arg>
+</arguments>
+
Sample command output:
+aprun -e DEBUG=true ... -j 20 e3sm.exe : ... -j 20 e3sm.exe
+
module_system
: How and what modules to load on this system. Module systems allow you to easily load multiple compiler environments on a machine. CIME provides support for two types of module tools: module and soft. If neither of these is available on your machine, simply set <module_system type="none"\>
.
environment_variables
: environment_variables to set on the systemThis contains sub-elements <env>
with the name
attribute specifying the environment variable name, and the element value specifying the corresponding environment variable value. If the element value is not set, the corresponding environment variable will be unset in your shell.
For example, the following sets the environment variable OMP_STACKSIZE
to 256M:
<env name="OMP_STACKSIZE">256M</env>
+
The following unsets this environment variable in the shell:
+<env name="OMP_STACKSIZE"></env>
+
Note
+These changes are ONLY activated for the CIME build and run environment, BUT NOT for your login shell. To activate them for your login shell, source either $CASEROOT/.env_mach_specific.sh or $CASEROOT/.env_mach_specific.csh, depending on your shell.
+CIME looks at the xml node BATCH_SPEC_FILE
in the config_files.xml file to identify supported out-of-the-box batch system details for the target model. The node has the following contents:
<entry id="BATCH_SPEC_FILE">
+ <type>char</type>
+ <default_value>$CIMEROOT/cime_config/$MODEL/machines/config_batch.xml</default_value>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>file containing batch system details for target system (for documentation only - DO NOT EDIT)</desc>
+ <schema>$CIMEROOT/cime_config/xml_schemas/config_batch.xsd</schema>
+</entry>
+
The config_batch.xml schema is defined in $CIMEROOT/config/xml_schemas/config_batch.xsd.
+CIME supports these batch systems: pbs, cobalt, lsf and slurm.
+The entries in config_batch.xml are hierarchical.
+General configurations for each system are provided at the top of the file.
Specific modifications for a given machine are provided below. In particular each machine should define its own queues.
Following is a machine-specific queue section. This section details the parameters for each queue on the target machine.
The last section describes several things:
+each job that will be submitted to the queue for a CIME workflow,
the template file that will be used to generate that job,
the prerequisites that must be met before the job is submitted, and
the dependencies that must be satisfied before the job is run.
By default the CIME workflow consists of two jobs (case.run, case.st_archive).
+In addition, there is case.test job that is used by the CIME system test workflow.
+CIME looks at the xml element CMAKE_MACROS_DIR
in the config_files.xml file to identify supported out-of-the-box compiler details for the target model. The node has the following contents:
<entry id="CMAKE_MACROS_DIR">
+ <type>char</type>
+ <default_value>$CIMEROOT/config/$MODEL/machines/cmake_macros</default_value>
+ <group>case_last</group>
+ <file>env_case.xml</file>
+ <desc>Directory containing cmake macros (for documentation only - DO NOT EDIT)</desc>
+</entry>
+
Additional compilers are made avilable by adding cmake macros files to the directory pointed to by CMAKE_MACROS_DIR or to your $HOME/.cime directory.
+The config_compilers.xml file defines compiler flags for building CIME (and also CESM and E3SM prognostic CIME-driven components).
+General compiler flags (e.g., for the gnu compiler) that are machine- and componen-independent are listed first.
Compiler flags specific to a particular operating system are listed next.
Compiler flags that are specific to particular machines are listed next.
Compiler flags that are specific to particular CIME-driven components are listed last.
The order of listing is a convention and not a requirement.
+The possible elements and attributes that can exist in the file are documented in $CIME/config/xml_schemas/config_compilers_v2.xsd.
+To clarify several conventions:
+The <append>
element implies that any previous definition of that element’s parent will be appended with the new element value.
+As an example, the following entry in config_compilers.xml would append the value of CPPDEFS
with -D $OS
where $OS
is the environment value of OS
.
<compiler>
+ <CPPDEFS>
+ <append> -D<env>OS</env> </append>
+ </CPPDEFS>
+</compiler>
+
The <base>
element overwrites its parent element’s value. For example, the following entry would overwrite the CONFIG_ARGS
for machine melvin
with a gnu
compiler to be --host=Linux
.
<compiler MACH="melvin" COMPILER="gnu">
+ <CONFIG_ARGS>
+ <base> --host=Linux </base>
+ </CONFIG_ARGS>
+</compiler>
+
The CIME coupling infrastructure is capable of running multiple +component instances (ensembles) under one model executable. There are +two modes of ensemble capability, single driver in which all component +instances are handled by a single driver/coupler component or +multi-driver in which each instance includes a separate driver/coupler +component. In the multi-driver mode the entire model is duplicated +for each instance while in the single driver mode only active +components need be duplicated. In most cases the multi-driver mode +will give better performance and should be used.
+The primary motivation for this development was to be able to run an +ensemble Kalman-Filter for data assimilation and parameter estimation +(UQ, for example). However, it also provides the ability to run a set +of experiments within a single model executable where each instance +can have a different namelist, and to have all the output go to one +directory.
+An F compset is used in the following example. Using the +multiple-instance code involves the following steps:
+1. Create the case.
+> create_newcase --case Fmulti --compset F2000_DEV --res f19_f19_mg17
+> cd Fmulti
+
2. Assume this is the out-of-the-box pe-layout:
+Comp NTASKS NTHRDS ROOTPE
+CPL : 144/ 1; 0
+ATM : 144/ 1; 0
+LND : 144/ 1; 0
+ICE : 144/ 1; 0
+OCN : 144/ 1; 0
+ROF : 144/ 1; 0
+GLC : 144/ 1; 0
+WAV : 144/ 1; 0
+ESP : 1/ 1; 0
+
The atm, lnd, rof and glc are active components in this compset. The ocn is +a prescribed data component, cice is a mixed prescribed/active +component (ice-coverage is prescribed), and wav and esp are stub +components.
+Let’s say we want to run two instances of CAM in this experiment. We +will also have to run two instances of CLM, CICE, RTM and GLC. However, we +can run either one or two instances of DOCN, and we can ignore the +stub components since they do not do anything in this compset.
+To run two instances of CAM, CLM, CICE, RTM, GLC and DOCN, invoke the following :ref: xmlchange<modifying-an-xml-file> commands in your $CASEROOT directory:
+> ./xmlchange NINST_ATM=2
+> ./xmlchange NINST_LND=2
+> ./xmlchange NINST_ICE=2
+> ./xmlchange NINST_ROF=2
+> ./xmlchange NINST_GLC=2
+> ./xmlchange NINST_OCN=2
+
As a result, you will have two instances of CAM, CLM and CICE (prescribed), RTM, GLC, and DOCN, each running concurrently on 72 MPI tasks and all using the same driver/coupler component. In this single driver/coupler mode the number of tasks for each component instance is NTASKS_COMPONENT/NINST_COMPONENT and the total number of tasks is the same as for the single instance case.
+Now consider the multi driver model. +To use this mode change
+> ./xmlchange MULTI_DRIVER=TRUE
+
This configuration will run each component instance on the original 144 tasks but will generate two copies of the model (in the same executable) for a total of 288 tasks.
+3. Set up the case
+> ./case.setup
+
A new user_nl_xxx_NNNN file is generated for each component instance when case.setup is called (where xxx is the component type and NNNN is the number of the component instance). +When calling case.setup with the env_mach_pes.xml file specifically, these files are created in $CASEROOT:
+user_nl_cam_0001 user_nl_clm_0001 user_nl_docn_0001 user_nl_cice_0001
+user_nl_cism_0001 user_nl_mosart_0001
+user_nl_cam_0002 user_nl_clm_0002 user_nl_docn_0002 user_nl_cice_0002
+user_nl_cism_0002 user_nl_mosart_0002
+user_nl_cpl
+
The namelist for each component instance can be modified by changing the corresponding user_nl_xxx_NNNN file. +Modifying user_nl_cam_0002 will result in your namelist changes being active ONLY for the second instance of CAM. +To change the DOCN stream txt file instance 0002, copy docn.streams.txt.prescribed_0002 to your $CASEROOT directory with the name user_docn.streams.txt.prescribed_0002 and modify it accordlingly.
+Also keep these important points in mind:
+Note that these changes can be made at create_newcase time with option –ninst # where # is a positive integer, use the additional logical option –multi-driver to invoke the multi-driver mode.
Multiple component instances can differ ONLY in namelist settings; they ALL use the same model executable.
Calling case.setup with --clean
DOES NOT remove the user_nl_xxx_NN (where xxx is the component name) files created by case.setup.
A special variable NINST_LAYOUT is provided for some experimental compsets, its value should be +‘concurrent’ for all but a few special cases and it cannot be used if MULTI_DRIVER=TRUE.
In create_test these options can be invoked with testname modifiers _N# for the single driver mode and _C# for the multi-driver mode. These are mutually exclusive options, they cannot be combined.
In create_newcase you may use –ninst # to set the number of instances and –multi-driver for multi-driver mode.
In multi-driver mode you will always get 1 instance of each component for each driver/coupler, if you change a case using xmlchange MULTI_COUPLER=TRUE you will get a number of driver/couplers equal to the maximum NINST value over all components.
Once a compset and resolution for a case has been defined, CIME +provides ways to define the processor layout the case will use.
+CIME cases have significant flexibility with respect to the layout of +components across different hardware processors. There are up to eight +unique models (atm, lnd, rof, ocn, ice, glc, wav, cpl) that are +managed independently by the CIME driver, each with a unique MPI +communicator. In addition, the driver runs on the union of all +processors and controls the sequencing and hardware partitioning.
+CIME looks at the xml element PES_SPEC_FILE
in the $CIMEROOT/config/$model/config_files.xml file to determine where
+to find the supported out-of-the-box model pe-settings for the primary component (See Compsets for definition of primary component.)
When your run create_newcase, CIME identifies the primary component and the setting of the PES_SPEC_FILE
in the standard output.
By default, each primary component has a config_pes.xml file in +its cime_config directory. That file specifies out-of-the-box +pe-layout for compsets that the primary component defines. Currently, +the pe-layout can have dependencies on the compset, the model grid and +the target machine. Finally, there might be more than one +out-of-the-box pe-layout that could be used for a compset/grid/machine +combination: one for a low processor setting and one for a high +processor setting.
+A typical entry in a config_pes.xml looks like this:
+<grid name="a%T62">
+ <mach name="cheyenne">
+ <pes pesize="any" compset="DATM%IAF">
+ .......
+ </pes>
+ </mach>
+</grid>
+
Currently, the pesize can have values of [any,S,M,L,X1,X2]
.
Given the various dependencies, CIME uses an order of precedence to determine the optimal match. This order is as follows:
+grid match
+<grid name="any">
are used in the subsequent search.machine match
+<mach>
nodes.<machine name="any">
are used in the subsequent search.pesize and compset match
+<pes>
nodes.<pes pesize="any" compset="any">
is used.When create_newcase is called, it outputs the matches that are found in determining the best out-of-the-box pe-layout.
+Optimizing the throughput and efficiency of a CIME experiment often +involves customizing the processor (PE) layout. (See load +balancing.) CIME provides significant +flexibility with respect to the layout of components across different +hardware processors. In general, the CIME components – atm, lnd, +ocn, and so on – can run on overlapping or mutually unique +processors. While each component is associated with a unique MPI +communicator, the CIME driver runs on the union of all processors and +controls the sequencing and hardware partitioning.
+The pe-layout settings are controlled by the $CASEROOT
file
+env_mach_pes.xml file. Variables in this file determine the number
+of MPI tasks and OpenMP threads for each component, the number of
+instances of each component and the layout of the components across
+the hardware processors. The entries in env_mach_pes.xml have the
+following meanings:
XML variable |
+Description |
+
---|---|
MAX_MPITASKS_PER_NODE |
+The maximum number of MPI tasks per node. This is defined in config_machines.xml and therefore given a default setting, but can be user modified. |
+
MAX_TASKS_PER_NODE |
+The total number of (MPI tasks) * (OpenMP threads) allowed on a node. This is defined in config_machines.xml and therefore given a default setting, but can be user modified. Some computational platforms use a special software customized for the target hardware called symmetric multi-threading (SMT). This allows for over-subscription of the hardware cores. In cases where this is beneficial to model performance, the variable |
+
NTASKS |
+Total number of MPI tasks. A negative value indicates nodes rather than tasks, where MAX_MPITASKS_PER_NODE * -NTASKS equals the number of MPI tasks. |
+
NTHRDS |
+Number of OpenMP threads per MPI task. |
+
ROOTPE |
+The global MPI task of the component root task; if negative, indicates nodes rather than tasks. The root processor for each component is set relative to the MPI global communicator. |
+
PSTRID |
+The stride of MPI tasks across the global set of pes (for now set to 1). This variable is currently not used and is a placeholder for future development. |
+
NINST |
+The number of component instances, which are spread evenly across NTASKS. |
+
COST_PER_NODE |
+The numbers of cores/node used for accounting purposes. The user should not normally need to set this - but it is useful for understanding how you will be charged. |
+
Each CIME component has corresponding entries for NTASKS
, NTHRDS
, ROOTPE
and NINST
in the env_mach_pes.xml file. The layout of components on processors has no impact on the science.
+If all components have identical NTASKS
, NTHRDS
, and ROOTPE
settings, all components will exectute sequentially on the same hardware processors.
Hint
+To view the current settings, use the pelayout tool
+The time sequencing is hardwired into the driver. Changing +processor layouts does not change intrinsic coupling lags or coupling +sequencing.
+The coupler component has its own processor set for doing +computations such as mapping, merging, diagnostics, and flux +calculation. This is distinct from the driver, which always +runs on the union of all processors to manage model concurrency and +sequencing.
+For a fully active configuration, the atmosphere component is +hardwired in the driver to never run concurrently with the land or ice +component. Performance improvements associated with processor layout +concurrency therefore are constrained in this case such that there is +never a performance reason not to overlap the atmosphere component +with the land and ice components. Beyond that constraint, the land, +ice, coupler and ocean models can run concurrently, and the ocean +model can also run concurrently with the atmosphere model.
+Note
+if env_mach_pes.xml is modified after case.setup has been called, then you must run case.setup –reset and the call case.build. case.build will only recompile any source code that depends on values in env_mach_pes.xml
+Resources for your case will be allocated according to the following logic.
+NTASKS
* NTHRDS
is the total number of hardware processors allocated to a component.
The total number of cores that are allocated will be based on the product of (1) and (2) below where
+MAX(ROOTPE(comp) + NTASKS(comp))
across all components
MAX(NTHRDS)
across all components
In the following example, the atmosphere and ocean will run concurrently. The atmosphere will use 16 MPI tasks each with 4 threads per task for a total of 64 cores. The ocean will use 16 MPI tasks with 1 thread per task. BUT since the atmosphere has 4 threads, the ocean will use 64 total cores. The total number of cores will be 128. The atmosphere will run on MPI tasks 0-15 and the ocean will run on MPI tasks 16-31 in the global MPI communicators.
+++++NTASKS_ATM=16 NTHRDS_ATM=4 ROOTPE_ATM=0 +NTASKS_OCN=16 NTHRDS_OCN=1 ROOTPE_OCN=16 +
CIME ensures that the batch submission script (case.submit ) will automatically requests 128
+hardware processors, and the first 16 MPI tasks will be laid out on
+the first 64 hardware processors with a stride of 4. The next 16 MPI
+tasks are laid out on the second set of 64 hardware processors in the
+same manner, even though the ocean is not threaded. If you had set
+ROOTPE_OCN
to 64 in this example, a total of 312 processors would
+be requested, the atmosphere would be laid out on the first 64
+hardware processors in 16x4 fashion, and the ocean model would be laid
+out on hardware processors 255-311. Hardware processors 64-254 would
+be allocated but completely idle.
We strongly encourage you to use the preview_run script to review the environment +and job submit commands for your case.
+Load balancing is the practice of specifying a processor layout for a given model configuration +(compset, grid, and so on) to maximize simulation speed while minimizing processor idle time. +For a fixed total number of processors, the goal of this optimization is to achieve maximum throughput. +For a set of processor counts, the purpose is to find several “sweet spots” where +the model is minimally idle, cost is relatively low, and the throughput is relatively high.
+As with most models, increasing total processors normally results in both increased throughput +and increased cost. +If models scaled linearly, the cost would remain constant across different processor counts, +but models generally don’t scale linearly and the cost increases as processor count increases.
+Performing a load-balancing exercise on a proposed case before +undertaking a long production run is recommended practice. Load +balancing requires you to consider a number of factors, such as which +components are run; their absolute and relative resolution; cost, +scaling and processor count sweet spots for each component; and +internal load imbalance within a component.
+It is often best to load balance a system with all significant +run-time I/O turned off because it occurs infrequently, typically just +one timestep per simulated month. It is best treated as a separate cost as it +can otherwise bias interpretation of the overall balance. Also, the +use of OpenMP threading in some or all of the components is dependent +on the hardware/OS support as well as whether the system supports +running all MPI and mixed MPI/OpenMP on overlapping processors for +different components.
+Finally, decide whether components should run sequentially, concurrently, or in some combination.
+Typically, a series of short test runs with the desired production +configuration can establish a reasonable load balance setup for the +production job. The timing output can be used to compare test runs to +help determine the optimal load balance.
+Changing the pe layout of the model has NO IMPACT on the scientific +results. The basic order of operations and calling sequence are +hardwired into the driver and do not change with the pe +layout. However, both CESM and E3SM do impose some contraints in the +tempororal evolution of the components. For example, the prognostic +atmosphere model always run sequentially with the ice and land models +for scientific reasons. As a result, running the atmosphere +concurrently with the ice and land will result in idle processors at +some point in the timestepping sequence.
+Hint
+If you need to load balance a fully coupled case, use the Load Balancing Tool
+One approach to load balancing
+Carry out a PFS test. This test is by default a +20-day model run with restarts and history output turned off. This +should help you find the layout that has the best load balance for the +targeted number of processors. This provides a reasonable performance +estimate for the production run for most of the runtime.
+Seasonal variation and spin-up costs can change performance over time, +so even after a production run has started, review the timing output +occasionally to see if any layout changes might improve throughput or +decrease cost.
+In determining an optimal load balance for a specific configuration, +two pieces of information are useful.
+Which components are most expensive.
How individual components scale. Do they run faster with all MPI or +mixed MPI/OpenMP decomposition strategies? What are their optimal +decompositions at each processor count? If the cost and scaling of +the components are unknown, several short tests with arbitrary +component pe counts can help establish component scaling and sweet +spots.
Determining an optimal load balance
+Start with the most expensive component and a fixed optimal processor count and decomposition for that component.
Vary the concurrency and pe counts of the other components.
Identify a few potential load balance configurations, then run each a few times to establish run-to-run variability and determine the best layout.
In all cases, review the component run times in the timing output file for both overall throughput and independent component timings. Identify idle processors by considering the component concurrency in conjunction with the component timing.
+In general, a few component layout options are most reasonable:
+fully sequential,
fully sequential except the ocean running concurrently,
fully concurrent except the atmosphere running sequentially with the ice, rof, and land components.
The concurrency is limited in part by hardwired sequencing in the +driver. The sequencing is set by scientific constraints, although +there may be some addition flexibility with respect to concurrency +when running with mixed active and data models.
+Some general rules for finding optimal configurations
+Make sure you have set a processor layout where each hardware processor is assigned to at least one component. There is rarely a reason to have completely idle processors.
Make sure your cheapest components keep up with your most expensive components. In other words, a component that runs on 1024 processors should not be waiting on a component running on 16 processors.
Before running the job, make sure the batch queue settings are set correctly for your run. Review the account numbers, queue names and time limits. The ideal time limit, queue and run length are dependent on each other and on the current model throughput.
Take full advantage of the hardware resources. If you are charged by the 32-way node, you might as well target a total processor count that is a multiple of 32.
Keep a single component on a single node, if possible, to minimize internal component communication cost.
Assume that hardware performance can vary due to contention on the interconnect, file systems, or other areas. If you are unsure of a timing result, run cases multiple times.
The pe-layout and the associated timings are found in the timing files generated for your run.
+One of the first steps for many users is getting CIME-based models running on their local machine. +This section describes that process.
+The machine needs to have:
+a functioning MPI environment (unless you plan to run on a single core with the CIME mpi-serial library).
build tools gmake and cmake,
a netcdf library version 4.3 or newer built with the same compiler you will use for CIME.
A pnetcdf library is optional.
+If you are using MPI, make sure you can run a basic MPI parallel program on your machine before you attempt a CIME port. You can use this MPI example to check.
+It is usually very helpful to assure that you can run a basic mpi parallel program on your machine prior to attempting a CIME port. +Understanding how to compile and run the program fhello_world_mpi.F90 shown here could potentially save many hours of frustration.
+program fhello_world_mpi.F90
+ use mpi
+ implicit none
+ integer ( kind = 4 ) error
+ integer ( kind = 4 ) id
+ integer p
+ character(len=MPI_MAX_PROCESSOR_NAME) :: name
+ integer clen
+ integer, allocatable :: mype(:)
+ real ( kind = 8 ) wtime
+
+ call MPI_Init ( error )
+ call MPI_Comm_size ( MPI_COMM_WORLD, p, error )
+ call MPI_Comm_rank ( MPI_COMM_WORLD, id, error )
+ if ( id == 0 ) then
+ wtime = MPI_Wtime ( )
+
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) 'HELLO_MPI - Master process:'
+ write ( *, '(a)' ) ' FORTRAN90/MPI version'
+ write ( *, '(a)' ) ' '
+ write ( *, '(a)' ) ' An MPI test program.'
+ write ( *, '(a)' ) ' '
+ write ( *, '(a,i8)' ) ' The number of processes is ', p
+ write ( *, '(a)' ) ' '
+ end if
+ call MPI_GET_PROCESSOR_NAME(NAME, CLEN, ERROR)
+ write ( *, '(a)' ) ' '
+ write ( *, '(a,i8,a,a)' ) ' Process ', id, ' says "Hello, world!" ',name(1:clen)
+
+ call MPI_Finalize ( error )
+end program
+
As an example, on a MAC with 2 cores that has mpich with gnu fortran you would issue the following two commands:
+> mpif90 fhello_world_mpi.F90 -o hello_world
+> mpirun -np 2 ./hello_world
+
The distribution of CESM includes machines called homebrew and centos7-linux in the file $CIMEROOT/config/cesm/machines/config_machines.xml. +Please see the instructions in the file to create the directory structure and use these generic machine definitions.
+Porting CIME involves several steps. The first step is to define your machine. You can do this in one of two ways:
+You can edit $CIMEROOT/config/$model/machines/config_machines.xml and add an appropriate section for your machine.
You can use your $HOME/.cime directory (see CIME config and hooks).
+In particular, you can create a $HOME/.cime/config_machines.xml file with the definition for your machine.
+A template to create this definition is provided in $CIMEROOT/config/xml_schemas/config_machines_template.xml. More details are provided in the template file.
+In addition, if you have a batch system, you will also need to add a config_batch.xml file to your $HOME/.cime directory.
+All files in $HOME/.cime/ are appended to the xml objects that are read into memory from the $CIME/config/$model, where $model is either e3sm
or cesm
.
Note
+If you use method (2), you can download CIME updates without affecting your machine definitions in $HOME/.cime.
+Note
+If you will be supporting many users on your new machine, then we recommend using method (1) and issuing a GitHub pull request with your machine updates.
+In what follows we outline the process for method (2) above:
+Create a $HOME/.cime directory and create a config_machines.xml file in that directory.
+This file contains all the information you must set in order to configure a new machine to be CIME-compliant.
+Fill in the contents of $HOME/.cime/config_machines.xml that are specific to your machine. For more details see the config_machines.xml file.
+Check to ensure that your config_machines.xml file conforms to the CIME schema definition by doing the following:
+xmllint --noout --schema $CIME/config/xml_schemas/config_machines.xsd $HOME/.cime/config_machines.xml
+
If you find that you need to introduce compiler settings specific to your machine, create a $HOME/.cime/*.cmake file. +The default compiler settings are defined in $CIME/config/$model/machines/cmake_macros/.
If you have a batch system, you may also need to create a $HOME/.cime/config_batch.xml file. +Out-of-the-box batch settings are set in $CIME/config/$model/machines/config_batch.xml.
Once you have defined a basic configuration for your machine in your $HOME/.cime xml files, run scripts_regression_test.py interactively. This test is found and must be run in the directory $CIMEROOT/scripts/tests/. +This performs a number of basic unit tests starting from the simplest and working toward more complicated ones. If you have problems running scripts_regression_tests.py, see scripts_regression_tests.
After running those steps correctly, you are ready to try a case at your target compset and resolution.
+The following port validation is recommended for any new machine. +Carrying out these steps does not guarantee the model is running +properly in all cases nor that the model is scientifically valid on +the new machine.
+In addition to these tests, detailed validation should be carried out +for any new production run. That means verifying that model restarts +are bit-for-bit identical with a baseline run, that the model is +bit-for-bit reproducible when identical cases are run for several +months, and that production cases are monitored carefully as they +integrate forward to identify any potential problems as early as +possible.
+Users are responsible for their own validation process, +especially with respect to science validation.
+These are the recommended steps for validating a port for the CESM model:
+Verify basic functionality of your port by performing the cheyenne “prealpha” tests on your machine. This can be done by issuing the following command:
+./create_test --xml-category prealpha --xml-machine cheyenne --xml-compiler intel --machine <your_machine_name> --compiler <your_compiler_name>
+
This command will run the prealpha tests defined for cheyenne with the intel compiler, but will run them on your machine with your compiler. +These tests will be run in the $CIME_OUTPUT_ROOT. To see the results of tests, you need to do the following:
+> $CIME_OUTPUT_ROOT/cs.status.[testid]
+
where testid was indicated in the output when calling create_test
+Carry out ensemble consistency tests:
+This is described in $CIMEROOT/tools/statistical_ensemble_test/README. +The CESM-ECT (CESM Ensemble Consistency Test) determines whether a new simulation set up (new machine, compiler, etc.) is statistically distinguishable from an accepted ensemble. +The ECT process involves comparing several runs (3) generated with the new scenario to an ensemble built on a trusted machine (currently cheyenne). +The python ECT tools are located in the pyCECT subdirectory **$CIMEROOT/tools/statistical_ensemble_test/pyCECT.
+The verification tools in the CESM-ECT suite are:
+CAM-ECT
: detects issues in CAM and CLM (12 month runs)
UF-CAM-ECT
: detects issues in CAM and CLM (9 time step runs)
POP-ECT
: detects issues in POP and CICE (12 month runs)
Follow the instructions in the README file to generate three ensemble runs for any of the above tests that are most relevant to your port. +Then please go to the CESM2 ensemble verification website, where you can upload your files and subsequently obtain a quick response as to the success or failure of your verification.
+Once you have performed the verification that your port is successful, +you will want to determine the optimal pe-layout for your target +configurations (i.e. compset/resolution combinations). See the file +$CIMEROOT/tools/load_balancing_tools/README to understand how to +utilize the load balancing utilty. This utility finds reasonable PE +layouts for CIME-driven models. It will find these from timing files +you provide or from runs done by the tool.
+Once you are happy with the PE-layout for your target configuration, +you can it to the relevant config_pes.xml file for the component +that is responsible for generating the PE-layout for the target +configuration (this is normally referred to as the “primary” +component).
+Timing summaries for every successful case run, are located in the
+case subdirectory $CASEROOT/timing. In addition, every
+cpl.log.timestamp output file contains diagnostic timing
+information. Search for tStamp
in this file to see this
+information. The timing information is useful for tracking down
+temporal variability in model cost due to either inherent model
+variability cost (I/O, spin-up, seasonal, and so on) or hardware. The
+model daily cost generally is pretty constant unless I/O is written
+intermittently, such as at the end of the month.
The script case.submit will submit your run to the batch queueing system on your machine. +If you do not have a batch queueing system, case.submit will start the job interactively, given that you have a proper MPI environment defined. +Running case.submit is the ONLY way you should start a job.
+To see the options to case.submit, issue the command
+> ./case.submit --help
+
A good way to see what case.submit will do, is to first call preview_run
+> ./preview_run
+
which will output the environment for your run along with the batch submit and mpirun commands. +As an example, on the NCAR machine, cheyenne, for an A compset at the f19_g17_rx1 resolution, the following is output from preview_run:
+CASE INFO:
+ nodes: 1
+ total tasks: 36
+ tasks per node: 36
+ thread count: 1
+
+BATCH INFO:
+ FOR JOB: case.run
+ENV:
+ module command is /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python purge
+ module command is /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python load ncarenv/1.2 intel/17.0.1 esmf_libs mkl esmf-7.0.0-defio-mpi-O mpt/2.16 netcdf-mpi/4.5.0 pnetcdf/1.9.0 ncarcompilers/0.4.1
+ Setting Environment OMP_STACKSIZE=256M
+ Setting Environment TMPDIR=/glade/scratch/mvertens
+ Setting Environment MPI_TYPE_DEPTH=16
+SUBMIT CMD:
+ qsub -q regular -l walltime=12:00:00 -A P93300606 .case.run
+
+FOR JOB: case.st_archive
+ ENV:
+ module command is /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python purge
+ module command is /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python load ncarenv/1.2 intel/17.0.1 esmf_libs mkl esmf-7.0.0-defio-mpi-O mpt/2.16 netcdf-mpi/4.5.0 pnetcdf/1.9.0 ncarcompilers/0.4.1
+ Setting Environment OMP_STACKSIZE=256M
+ Setting Environment TMPDIR=/glade/scratch/mvertens
+ Setting Environment MPI_TYPE_DEPTH=16
+ Setting Environment TMPDIR=/glade/scratch/mvertens
+ Setting Environment MPI_USE_ARRAY=false
+SUBMIT CMD:
+ qsub -q share -l walltime=0:20:00 -A P93300606 -W depend=afterok:0 case.st_archive
+
+MPIRUN:
+ mpiexec_mpt -np 36 -p "%g:" omplace -tm open64 /glade/scratch/mvertens/jim/bld/cesm.exe >> cesm.log.$LID 2>&1
+
Each of the above sections is defined in the various $CASEROOT xml files and the associated variables can be modified using the +xmlchange command (or in the case of tasks and threads, this can also be done with the pelayout command).
+The PE layout is set by the xml variables NTASKS, NTHRDS and ROOTPE. To see the exact settings for each component, issue the command
+./xmlquery NTASKS,NTHRDS,ROOTPE
+
To change all of the NTASKS settings to say 30 and all of the NTHRDS to 4, you can call
+./xmlchange NTASKS=30,NTHRDS=4
+
To change JUST the ATM NTASKS to 8, you can call
+./xmlchange NTASKS_ATM=8
+
Submit parameters are set by the xml variables in the file env_batch.xml. This file is special in certain xml variables can appear in more than one group.
+NOTE: The groups are the list of jobs that are submittable for a case.
+Normally, the minimum set of groups are case.run and case.st_archive.
+We will illustrate how to change an xml variable in env_batch.xml using the xml variable JOB_WALLCLOCK_TIME
.
To change JOB_WALLCLOCK_TIME
for all groups to 2 hours for cheyenne, use
./xmlchange JOB_WALLCLOCK_TIME=02:00:00
+
To change JOB_WALLCLOCK_TIME
to 20 minutes for cheyenne for just case.run, use
./xmlchange JOB_WALLCLOCK_TIME=00:20:00 --subgroup case.run
+
Before you submit the case using case.submit, make sure the batch queue variables are set correctly for your run
+In particular, make sure that you have appropriate account numbers (PROJECT
), time limits (JOB_WALLCLOCK_TIME
), and queue (JOB_QUEUE
).
Also modify $CASEROOT/env_run.xml for your case using xmlchange.
+Once you have executed case.setup and case.build , call case.submit +to submit the run to your machine’s batch queue system.
+> cd $CASEROOT
+> ./case.submit
+
When called, the case.submit script will:
+Load the necessary environment.
Confirm that locked files are consistent with the current xml files.
Run preview_namelist, which in turn will run each component’s cime_config/buildnml script.
Run check_input_data to verify that the required data are present.
Submit the job to the batch queue. which in turn will run the case.run script.
Upon successful completion of the run, case.run will:
+Put timing information in $CASEROOT/timing. +See model timing data for details.
Submit the short-term archiver script case.st_archive to the batch queue if $DOUT_S
is TRUE.
+Short-term archiving will copy and move component history, log, diagnostic, and restart files from $RUNDIR
to the short-term archive directory $DOUT_S_ROOT
.
Resubmit case.run if $RESUBMIT
> 0.
The $CASEROOT/CaseStatus file contains a log of all the job states and xmlchange commands in chronological order. +Below is an example of status messages:
+2017-02-14 15:29:50: case.setup starting
+---------------------------------------------------
+2017-02-14 15:29:54: case.setup success
+---------------------------------------------------
+2017-02-14 15:30:58: xmlchange success <command> ./xmlchange STOP_N=2,STOP_OPTION=nmonths </command>
+---------------------------------------------------
+2017-02-14 15:31:26: xmlchange success <command> ./xmlchange STOP_N=1 </command>
+---------------------------------------------------
+2017-02-14 15:33:51: case.build starting
+---------------------------------------------------
+2017-02-14 15:53:34: case.build success
+---------------------------------------------------
+2017-02-14 16:02:35: case.run starting
+---------------------------------------------------
+2017-02-14 16:20:31: case.run success
+---------------------------------------------------
+2017-02-14 16:20:45: st_archive starting
+---------------------------------------------------
+2017-02-14 16:20:58: st_archive success
+---------------------------------------------------
+
Note
+After a successful first run, set the env_run.xml variable $CONTINUE_RUN
to TRUE
before resubmitting or the job will not
+progress.
You may also need to modify the env_run.xml variables
+$STOP_OPTION
, $STOP_N
and/or $STOP_DATE
as well as
+$REST_OPTION
, $REST_N
and/or $REST_DATE
, and $RESUBMIT
+before resubmitting.
See the basic example for a complete example of how to run a case.
+There are several places to look for information if a job fails. +Start with the STDOUT and STDERR file(s) in $CASEROOT. +If you don’t find an obvious error message there, the +$RUNDIR/$model.log.$datestamp files will probably give you a +hint.
+First, check cpl.log.$datestamp, which will often tell you +when the model failed. Then check the rest of the component log +files. See troubleshooting run-time problems for more information.
+The check_input_data script determines if the required data files
+for your case exist on local disk in the appropriate subdirectory of
+$DIN_LOC_ROOT
. It automatically downloads missing data required for your simulation.
Note
+It is recommended that users on a given system share a common $DIN_LOC_ROOT
directory to avoid duplication on
+disk of large amounts of input data. You may need to talk to your system administrator in order to set this up.
The required input data sets needed for each component are found in the
+$CASEROOT/Buildconf directory. These files are generated by a call
+to preview_namlists and are in turn created by each component’s
+buildnml script. For example, for compsets consisting only of data
+models (i.e. A
compsets), the following files are created:
cpl.input_data_list
+datm.input_data_list
+dice.input_data_list
+docn.input_data_list
+drof.input_data_list
+
You can independently verify the presence of the required data by +using the following commands:
+> cd $CASEROOT
+> ./check_input_data --help
+> ./check_input_data
+
If data sets are missing, obtain them from the input data server(s) via the commands:
+> cd $CASEROOT
+> ./check_input_data --download
+
check_input_data
is automatically called by the case control
+system, when the case is built and submitted. So manual usage of this
+script is optional.
CIME has the ability to utilize multiple input data repositories, with
+potentially different protocols. The repositories are defined in the
+file $CIMEROOT/config/$model/config_inputdata.xml. The currently
+supported server protocols are: gridftp
, subversion
, ftp
and
+wget
. These protocols may not all be supported on your machine,
+depending on software configuration.
Note
+You now have the ability to create your own input data +repository and add it to the config_inputdata.xml. This +will permit you to easily collaborate by sharing your +required inputdata with others.
+The file env_run.xml contains variables that may be modified at +initialization or any time during the course of a model run. Among +other features, the variables comprise coupler namelist settings for +the model stop time, restart frequency, coupler history frequency, and +a flag to determine if the run should be flagged as a continuation run.
+At a minimum, you will need to set the variables $STOP_OPTION
and
+$STOP_N
. Other driver namelist settings then will have consistent and
+reasonable default values. The default settings guarantee that
+restart files are produced at the end of the model run.
By default, the stop time settings are:
+STOP_OPTION = ndays
+STOP_N = 5
+STOP_DATE = -999
+
The default settings are appropriate only for initial testing. Before
+starting a longer run, update the stop times based on the case
+throughput and batch queue limits. For example, if the model runs 5
+model years/day, set RESUBMIT=30, STOP_OPTION= nyears, and STOP_N=
+5
. The model will then run in five-year increments and stop after
+30 submissions.
The case initialization type is set using the $RUN_TYPE
variable in
+env_run.xml. A CIME run can be initialized in one of three ways:
startup
++In a startup run (the default), all components are initialized using +baseline states. These states are set independently by each component +and can include the use of restart files, initial files, external +observed data files, or internal initialization (that is, a “cold start”). +In a startup run, the coupler sends the start date to the components +at initialization. In addition, the coupler does not need an input data file. +In a startup initialization, the ocean model does not start until the second +ocean coupling step.
+
branch
++In a branch run, all components are initialized using a consistent +set of restart files from a previous run (determined by the +
+$RUN_REFCASE
and$RUN_REFDATE
variables in env_run.xml). +The case name generally is changed for a branch run, but it +does not have to be. In a branch run, the$RUN_STARTDATE
setting is +ignored because the model components obtain the start date from +their restart data sets. Therefore, the start date cannot be changed +for a branch run. This is the same mechanism that is used for +performing a restart run (where$CONTINUE_RUN
is set to TRUE in +the env_run.xml file). Branch runs typically are used when +sensitivity or parameter studies are required, or when settings for +history file output streams need to be modified while still +maintaining bit-for-bit reproducibility. Under this scenario, the +new case is able to produce an exact bit-for-bit restart in the same +manner as a continuation run if no source code or component namelist +inputs are modified. All models use restart files to perform this +type of run.$RUN_REFCASE
and$RUN_REFDATE
are required for +branch runs. To set up a branch run, locate the restart tar file or +restart directory for$RUN_REFCASE
and$RUN_REFDATE
from a +previous run, then place those files in the$RUNDIR
directory. +See Starting from a reference case.
hybrid
++A hybrid run is initialized like a startup but it uses +initialization data sets from a previous case. It is similar +to a branch run with relaxed restart constraints. +A hybrid run allows users to bring together +combinations of initial/restart files from a previous case +(specified by
+$RUN_REFCASE
) at a given model output date +(specified by$RUN_REFDATE
). Unlike a branch run, the starting +date of a hybrid run (specified by$RUN_STARTDATE
) can be +modified relative to the reference case. In a hybrid run, the model +does not continue in a bit-for-bit fashion with respect to the +reference case. The resulting climate, however, should be +continuous provided that no model source code or namelists are +changed in the hybrid run. In a hybrid initialization, the ocean +model does not start until the second ocean coupling step, and the +coupler does a “cold start” without a restart file.
The variable $RUN_TYPE
determines the initialization type. This
+setting is only important for the initial production run when
+the $CONTINUE_RUN
variable is set to FALSE. After the initial
+run, the $CONTINUE_RUN
variable is set to TRUE, and the model
+restarts exactly using input files in a case, date, and bit-for-bit
+continuous fashion.
The variable $RUN_STARTDATE
is the start date (in yyyy-mm-dd format)
+for either a startup run or a hybrid run. If the run is targeted to be
+a hybrid or branch run, you must specify values for $RUN_REFCASE
and
+$RUN_REFDATE
.
There are several xml variables that control how either a branch or a hybrid case can start up from another case.
+The initial/restart files needed to start up a run from another case are required to be in $RUNDIR
.
+The xml variable $GET_REFCASE
is a flag that if set will automatically prestaging the refcase restart data.
If $GET_REFCASE
is TRUE
, then the the values set by $RUN_REFDIR
, $RUN_REFCASE
, $RUN_REFDATE
and $RUN_TOD
are
+used to prestage the data by symbolic links to the appropriate path.
The location of the necessary data to start up from another case is controlled by the xml variable $RUN_REFDIR
.
If $RUN_REFDIR
is an absolute pathname, then it is expected that initial/restart files needed to start up a model run are in $RUN_REFDIR
.
If $RUN_REFDIR
is a relative pathname, then it is expected that initial/restart files needed to start up a model run are in a path relative to $DIN_LOC_ROOT
with the absolute pathname $DIN_LOC_ROOT/$RUN_REFDIR/$RUN_REFCASE/$RUN_REFDATE
.
If $RUN_REFDIR
is a relative pathname AND is not available in $DIN_LOC_ROOT
then CIME will attempt to download the data from the input data repositories.
If $GET_REFCASE
is FALSE
then the data is assumed to already exist in $RUNDIR
.
During a model run, each model component produces its own output
+data sets in $RUNDIR
consisting of history, initial, restart, diagnostics, output
+log and rpointer files. Component history files and restart files are
+in netCDF format. Restart files are used to either restart the same
+model or to serve as initial conditions for other model cases. The
+rpointer files are ascii text files that list the component history and
+restart files that are required for restart.
Archiving (referred to as short-term archiving here) is the phase of a model run when output data are
+moved from $RUNDIR
to a local disk area (short-term archiving).
+It has no impact on the production run except to clean up disk space
+in the $RUNDIR
which can help manage user disk quotas.
Several variables in env_run.xml control the behavior of +short-term archiving. This is an example of how to control the +data output flow with two variable settings:
+DOUT_S = TRUE
+DOUT_S_ROOT = /$SCRATCH/$user/$CASE/archive
+
The first setting above is the default, so short-term archiving is enabled. The second sets where to move files at the end of a successful run.
+Also:
+All output data is initially written to $RUNDIR
.
Unless you explicitly turn off short-term archiving, files are
+moved to $DOUT_S_ROOT
at the end of a successful model run.
Users generally should turn off short-term archiving when developing new code.
Standard output generated from each component is saved in $RUNDIR
+in a log file. Each time the model is run, a single coordinated datestamp
+is incorporated into the filename of each output log file.
+The run script generates the datestamp in the form YYMMDD-hhmmss, indicating
+the year, month, day, hour, minute and second that the run began
+(ocn.log.040526-082714, for example).
By default, each component also periodically writes history files
+(usually monthly) in netCDF format and also writes netCDF or binary
+restart files in the $RUNDIR
directory. The history and log files
+are controlled independently by each component. History output control
+(for example, output fields and frequency) is set in each component’s namelists.
The raw history data does not lend itself well to easy time-series +analysis. For example, CAM writes one or more large netCDF history +file(s) at each requested output period. While this behavior is +optimal for model execution, it makes it difficult to analyze time +series of individual variables without having to access the entire +data volume. Thus, the raw data from major model integrations usually +is post-processed into more user-friendly configurations, such as +single files containing long time-series of each output fields, and +made available to the community.
+For CESM, refer to the CESM2 Output Filename Conventions +for a description of output data filenames.
+Active components (and some data components) write restart files
+at intervals that are dictated by the driver via the setting of the
+$REST_OPTION
and $REST_N
variables in env_run.xml. Restart
+files allow the model to stop and then start again with bit-for-bit
+exact capability; the model output is exactly the same as if the model
+had not stopped. The driver coordinates the writing of restart
+files as well as the time evolution of the model.
Runs that are initialized as branch or hybrid runs require
+restart/initial files from previous model runs (as specified by the
+variables $RUN_REFCASE
and $RUN_REFDATE
). Pre-stage these files
+to the case $RUNDIR
(normally $EXEROOT/../run
) before the model
+run starts. Normally this is done by copying the contents of the
+relevant $RUN_REFCASE/rest/$RUN_REFDATE.00000 directory.
Whenever a component writes a restart file, it also writes a restart +pointer file in the format rpointer.$component. Upon a restart, each +component reads the pointer file to determine which file to read in +order to continue the run. These are examples of pointer files created +for a component set using full active model components.
+- rpointer.atm
+- rpointer.drv
+- rpointer.ice
+- rpointer.lnd
+- rpointer.rof
+- rpointer.cism
+- rpointer.ocn.ovf
+- rpointer.ocn.restart
+
If short-term archiving is turned on, the model archives the +component restart data sets and pointer files into +$DOUT_S_ROOT/rest/yyyy-mm-dd-sssss, where yyyy-mm-dd-sssss is the +model date at the time of the restart. (See below for more details.)
+If a run encounters problems and crashes, you will normally have to
+back up to a previous restart. If short-term archiving is enabled,
+find the latest $DOUT_S_ROOT/rest/yyyy-mm-dd-ssss/ directory
+and copy its contents into your run directory ($RUNDIR
).
Make sure that the new restart pointer files overwrite older files in
+in $RUNDIR
or the job may not restart in the correct place. You can
+then continue the run using the new restarts.
Occasionally, when a run has problems restarting, it is because the +pointer and restart files are out of sync. The pointer files +are text files that can be edited to match the correct dates +of the restart and history files. All of the restart files should +have the same date.
+The output data flow from a successful run depends on whether or not +short-term archiving is enabled, as it is by default.
+If no short-term archiving is performed, model output data remains
+remain in the run directory as specified by $RUNDIR
.
If short-term archiving is enabled, component output files are moved
+to the short-term archiving area on local disk, as specified by
+$DOUT_S_ROOT
. The directory normally is $EXEROOT/../../archive/$CASE.
+and has the following directory structure:
rest/yyyy-mm-dd-sssss/
+logs/
+atm/hist/
+cpl/hist
+glc/hist
+ice/hist
+lnd/hist
+ocn/hist
+rof/hist
+wav/hist
+....
+
The logs/ subdirectory contains component log files that were +created during the run. Log files are also copied to the short-term +archiving directory and therefore are available for long-term archiving.
+The rest/ subdirectory contains a subset of directories that each contains +a consistent set of restart files, initial files and rpointer +files. Each subdirectory has a unique name corresponding to the model +year, month, day and seconds into the day when the files were created. +The contents of any restart directory can be used to create a branch run +or a hybrid run or to back up to a previous restart date.
+Users may choose to follow their institution’s preferred method for long-term +archiving of model output. Previous releases of CESM provided an external +long-term archiver tool that supported mass tape storage and HPSS systems. +However, with the industry migration away from tape archives, it is no longer +feasible for CIME to support all the possible archival schemes available.
+CIME provides a capability to run a task on the compute nodes either +before or after the model run. CIME also provides a data assimilation +capability which will cycle the model and then a user defined task for +a user determined number of cycles.
+Variables PRERUN_SCRIPT
and POSTRUN_SCRIPT
can each be used to name
+a script which should be exectuted immediately prior starting or
+following completion of the CESM executable within the batch
+environment. The script is expected to be found in the case directory
+and will recieve one argument which is the full path to that
+directory. If the script is written in python and contains a
+subroutine with the same name as the script, it will be called as a
+subroutine rather than as an external shell script.
Variables DATA_ASSIMILATION
, DATA_ASSIMILATION_SCRIPT
, and
+DATA_ASSIMILATION_CYCLES
may also be used to externally control
+model evolution. If DATA_ASSIMILATION
is true after the model
+completes the DATA_ASSIMILATION_SCRIPT
will be run and then the
+model will be started again DATA_ASSIMILATION_CYCLES
times. The
+script is expected to be found in the case directory and will recieve
+two arguments, the full path to that directory and the cycle number.
+If the script is written in python and contains a subroutine with the
+same name as the script, it will be called as a subroutine rather than
+as an external shell script.
..: A simple example pre run script.
+#!/usr/bin/env python3
+import sys
+from CIME.case import Case
+
+def myprerun(caseroot):
+ with Case(caseroot) as case:
+ print ("rundir is ",case.get_value("RUNDIR"))
+
+ if __name__ == "__main__":
+ caseroot = sys.argv[1]
+ myprerun(caseroot)
+
After creating a case, some aspects of the case are fixed (any variables in env_case.xml). Changing the pe-layout +(see Changing Pes) or some aspects of the batch system you may be using must be modified before running +case.setup.
+After creating a case or changing aspects of a case, such as the pe-layout, call the case.setup command from $CASEROOT
.
+This creates the following additional files and directories in $CASEROOT
:
+++ +
++ + .case.run
+ A (hidden) file with the commands that will be used to run the model (such as “mpirun”)
+and any batch directives needed. The directive values are generated using the contents
+of env_mach_pes.xml. Running case.setup –clean
+will remove this file. This file should not be edited directly and instead controlled
+through XML variables in env_batch.xml. It should also never be run directly.
++ + CaseStatus
+ File containing a list of operations done in the current case.
+ + case.st_archive
+ Script to perform short term archiving to disk for your case
+output. Note that this script is run automatically by the normal CIME workflow.
++ + Depends.*
+ Lists of source code files that needs special build options.
+ + Macros.cmake
+ File containing machine-specific makefile directives for your target platform/compiler.
+This file is created if it does not already exist.
+The user can modify the file to change certain aspects of the build, such as compiler flags.
+Running case.setup –clean will not remove the file once it has been created. +However. if you remove or rename the Macros.make file, running
+case.setup recreates it.
++ + user_nl_xxx[_NNNN]
+ Files where all user modifications to component namelists are made.
+xxx is any one of the set of components targeted for the case.
+For example, for a full active CESM compset, xxx is cam, clm or rtm, and so on.
+NNNN goes from 0001 to the number of instances of that component. +(See multiple instances)
+For a case with 1 instance of each component (default), NNNN will not appear +in the user_nl file names.
+A user_nl file of a given name is created only once.
+Calling case.setup –clean will not remove any user_nl files.
+Changing the number of instances in the env_mach_pes.xml file will cause only
+new user_nl files to be added to
+$CASEROOT
.+ + CaseDocs/
+ Directory that contains all the component namelists for the run.
+This is for reference only and files in this directory SHOULD NOT BE EDITED since they will
+be overwritten at build time and runtime.
++ + .env_mach_specific.*
+ Files summarizing the module load commands and environment variables that are set when
+the scripts in
+$CASEROOT
are called. These files are not used by the case but can beuseful for debugging module load and environment settings.
++ + + software_environment.txt
+ This file records some aspects of the computing system on which the case is built,
+such as the shell environment.
+
create_test +is a powerful system testing capability provided by the CIME Case Control System. +create_test can, in one command, create a case, setup, build and run the case +according to the test type and return a PASS or FAIL for the test result.
+An individual test can be run as:
+$CIMEROOT/scripts/create_test $test_name
+
For example:
+$CIMEROOT/scripts/create_test ERP_ne4pg2_oQU480.F2010
+
Everything the test will do is controlled by parsing the test name. The elements of the test name are +explained next.
+Tests must be named with the following forms, [ ]=optional:
+TESTTYPE[_MODIFIERS].GRID.COMPSET[.MACHINE_COMPILER][.GROUP-TESTMODS]
+
NAME PART |
++ |
---|---|
+ | the general type of test, e.g. SMS. Options are listed in the following table and config_tests.xml. |
+
+ | Changes to the default settings for the test type. +See the following table and test_scheduler.py. |
+
GRID |
+The grid set (usually a grid alias). |
+
COMPSET |
+The compset, Can be a longname but usually a compset alias |
+
MACHINE |
+This is optional; if this value is not supplied, create_test +will probe the underlying machine. |
+
COMPILER |
+If this value is not supplied, use the default compiler for MACHINE. |
+
+ | This is optional. This points to a directory with |
+
The test types in CIME are all system tests: they compile all the code needed in a case, They test +functionality of the model such as restart capability, invariance with MPI task count, and short +term archiving. At this time, they do not test for scientific correctness.
+The currently supported test types are:
+TESTTYPE |
+Description |
+
---|---|
ERS |
+
|
+
ERS2 |
+Exact restart from startup (default 6 days + 5 days). +++ |
+
ERT |
+Longer version of ERS. Exact restart from startup, default 2 month + 1 month (ERS with info DBUG = 1). |
+
IRT |
+Exact restart from startup, (default 4 days + 7 days) with restart from interim file. |
+
ERIO |
+Exact restart from startup with different IO file types, (default 6 days + 5 days). |
+
ERR |
+Exact restart from startup with resubmit, (default 4 days + 3 days). |
+
ERRI |
+Exact restart from startup with resubmit, (default 4 days + 3 days). Tests incomplete logs option for st_archive. |
+
ERI |
+
|
+
ERP |
+
|
+
PEA |
+
|
+
PEM |
+
|
+
PET |
+
|
+
PFS |
+Performance test setup. History and restart output is turned off. (default 20 days) |
+
ICP |
+CICE performance test. |
+
OCP |
+POP performance test. (default 10 days) |
+
MCC |
+Multi-driver validation vs single-driver (both multi-instance). (default 5 days) |
+
NCK |
+
|
+
REP |
+Reproducibility: Two identical initial runs are bit for bit. (default 5 days) |
+
SBN |
+Smoke build-namelist test (just run preview_namelist and check_input_data). |
+
SMS |
+
|
+
SEQ |
+
|
+
DAE |
+Data assimilation test, default 1 day, two DA cycles, no data modification. |
+
PRE |
+
+
+ |
+
The tests run for a default length indicated above, will use default pelayouts for the case +on the machine the test runs on and its default coupler and MPI library. Its possible to modify +elements of the test through a test type modifier.
+MODIFIERS |
+Description |
+
---|---|
_C# |
+Set number of instances to # and use the multi driver (can’t use with _N). |
+
_CG |
+CALENDAR set to “GREGORIAN” |
+
_D |
+XML variable DEBUG set to “TRUE” |
+
_I |
+Marker to distinguish tests with same name - ignored. |
+
_Lo# |
+
|
+
_Mx |
+Set MPI library to x. |
+
_N# |
+Set number of instances to # and use a single driver (can’t use with _C). |
+
_Px |
+Set create_newcase’s |
+
_R |
+For testing in PTS_MODE or Single Column Model (SCM) mode. +For PTS_MODE, compile with mpi-serial. |
+
_Vx |
+
|
+
For example, this will run the ERP test with debugging turned on during compilation:
+CIMEROOT/scripts/create_test ERP_D.ne4pg2_oQU480.F2010
+
This will run the ERP test for 3 days instead of the default 11 days:
+CIMEROOT/scripts/create_test ERP_Ld3.ne4pg2_oQU480.F2010
+
You can combine testtype modifiers:
+CIMEROOT/scripts/create_test ERP_D_Ld3.ne4pg2_oQU480.F2010
+
create_test runs with out-of-the-box compsets and grid sets. Sometimes you may want to run a test with +modification to a namelist or other setting without creating an entire compset. CCS provides the testmods +capability for this situation.
+A testmod is a string at the end of the full testname (including machine and compiler) +with the form GROUP-TESTMODS which are parsed by create_test as follows:
+TESTMOD |
+Description |
+
---|---|
GROUP |
+Define the subdirectory of testmods_dirs and the parent directory of various testmods. |
+
TESTMODS |
+A subdirectory of GROUP containing files which set non-default values +of the set-up and run-time variables via namelists or xml_change commands. +Example: +++ |
+
For example, the ERP test for an E3SM F-case can be modified to use a different radiation scheme:
+CIMEROOT/scripts/create_test ERP_D_Ld3.ne4pg2_oQU480.F2010.pm-cpu_intel.eam-rrtmgp
+
This tells create_test to look in $e3sm/components/eam/cime_config/testdefs/testmods_dirs/eam/rrtmpg +where it finds the following lines in the shell_commands file:
+#!/bin/bash
+./xmlchange --append CAM_CONFIG_OPTS='-rad rrtmgp'
+
These commands are applied after the testcase is created and case.setup is called.
+The contents of each testmods directory can include
+user_nl_$components namelist variable=value pairs
+shell_commands xmlchange commands
+user_mods a list of other GROUP-TESTMODS which should be imported
+ but at a lower precedence than the local testmods.
+
eam/cime_config/testdefs/testmods_dirs/eam contains modifications for eam in an F-case test. You +might make a directory called eam/cime_config/testdefs/testmods_dirs/elm to modify the land model +in an F-case test.
+The “rrtmpg” directory contains the actual testmods to apply. +Note; do not use ‘-’ in the testmods directory name because it has a special meaning to create_test.
+Each test run by create_test includes the following mandatory steps:
+CREATE_NEWCASE: creating the create
XML: xml changes to case based on test settings
SETUP: setup case (case.setup)
SHAREDLIB_BUILD: build sharedlibs
MODEL_BUILD: build module (case.build)
SUBMIT: submit test (case.submit)
RUN: run test test
And the following optional phases:
+NLCOMP: Compare case namelists against baselines
THROUGHPUT: Compare throughput against baseline throughput
MEMCOMP: Compare memory usage against baseline memory usage
MEMLEAK: Check for memleak
COMPARE: Used to track test-specific comparions, for example, an ERS test would have a COMPARE_base_rest phase representing the check that the base result matched the restart result.
GENERATE: Generate baseline results
BASELINE: Compare results against baselines
Each phase within the test may be in one of the following states:
+PASS: The phase was executed successfully
FAIL: We attempted to execute this phase, but it failed. If this phase is mandatory, no further progress will be made on this test. A detailed explanation of the failure should be in TestStatus.log.
PEND: This phase will be run or is currently running but not complete
Multiple tests can be run by listing all of the test names on the command line:
+$CIMEROOT/scripts/create_test $test_name $test_name2
+
or by putting the test names into a file, one name per line:
+$CIMEROOT/scripts/create_test -f $file_of_test_names
+
To run a test with a non-default compiler:
+./create_test SMS.f19_f19.A --compiler intel
+
To run a test with baseline comparisons against baseline name ‘master’:
+./create_test SMS.f19_f19.A -c -b master
+
To run a test and update baselines with baseline name ‘master’:
+./create_test SMS.f19_f19.A -g -b master
+
To run a test with a non-default test-id:
+./create_test SMS.f19_f19.A -t my_test_id
+
To run a test and use a non-default test-root for your case dir:
+./create_test SMS.f19_f19.A -t $test_root
+
To run a test and use and put case, build, and run dirs all in the same root:
+./create_test SMS.f19_f19.A --output-root $output_root
+
To run a test and force it to go into a certain batch queue:
+./create_test SMS.f19_f19.A -q myqueue
+
The Case Control System supports more sophisticated ways to specify a suite of tests and +how they should be run. One approach uses XML files and the other uses python dictionaries.
+A pre-defined suite of tests can by run using the --xml
options to create_test,
+which harvest test names from testlist*.xml files.
+As described in https://github.com/ESCOMP/ctsm/wiki/System-Testing-Guide,
+to determine what pre-defined test suites are available and what tests they contain,
+you can run query_testlists.
Test suites are retrieved in create_test via 3 selection attributes:
+--xml-category your_category The test category.
+--xml-machine your_machine The machine.
+--xml-compiler your_compiler The compiler.
+
The search for test names can be restricted to a single test list using:
+--xml-testlist your_testlist
+
Omitting this results in searching all testlists listed in:
+cime/config/{cesm,e3sm}/config_files.xml
+
$CIMEROOT/scripts/query_testlists gathers descriptions of the tests and testlists available +in the XML format, the components, and projects.
+The --xml-{compiler,machine,category,testlist}
arguments can be used
+as in create_test (above) to focus the search.
+The ‘category’ descriptor of a test can be used to run a group of associated tests at the same time.
+The available categories, with the tests they encompass, can be listed by:
./query_testlists --define-testtypes
+
The --show-options
argument does the same, but displays the ‘options’ defined for the tests,
+such as queue, walltime, etc..
Adding a test requires first deciding which compset will be tested +and then finding the appropriate testlist_$component.xml file:
+components/$component/cime_config/testdefs/
+ testlist_$component.xml
+ testmods_dirs/$component/{TESTMODS1,TESTMODS2,...}
+cime_config/
+ testlist_allactive.xml
+ testmods_dirs/allactive/{defaultio,...}
+
You can optionally add testmods for that test in the testmods_dirs. +Testlists and testmods live in different paths for cime, drv, and components.
+If this test will only be run as a single test, you can now create a test name +and follow the individual test instructions for create_test.
+One can also define suites of tests in a file called tests.py typically located in $MODEL/cime_config/tests.py
+To run a test suite called e3sm_developer:
+./create_test e3sm_developer
+
One can exclude a specific test from a suite:
+./create_test e3sm_developer ^SMS.f19_f19.A
+
See create_test -h for the full list of options +`
+To add a test, open the MODEL/cime_config/tests.py file, you’ll see a python dict at the top +of the file called _TESTS, find the test category you want to +change in this dict and add your testcase to the list. Note the +comment at the top of this file indicating that you add a test with +this format: test>.<grid>.<compset>, and then there is a second +argument for mods. Machine and compiler are added later depending on where +create_test is invoked and its arguments.
+Existing tests can be listed using the cime/CIME/Tools/list_e3sm_tests script.
+For example:
+/list_e3sm_tests -t compsets e3sm_developer
+
Will list all the compsets tested in the e3sm_developer test suite.
+Interpreting test output is pretty easy. Looking at an example:
+% ./create_test SMS.f19_f19.A
+
+Creating test directory /home/jgfouca/e3sm/scratch/SMS.f19_f19.A.melvin_gnu.20170504_163152_31aahy
+RUNNING TESTS:
+ SMS.f19_f19.A.melvin_gnu
+Starting CREATE_NEWCASE for test SMS.f19_f19.A.melvin_gnu with 1 procs
+Finished CREATE_NEWCASE for test SMS.f19_f19.A.melvin_gnu in 4.170537 seconds (PASS)
+Starting XML for test SMS.f19_f19.A.melvin_gnu with 1 procs
+Finished XML for test SMS.f19_f19.A.melvin_gnu in 0.735993 seconds (PASS)
+Starting SETUP for test SMS.f19_f19.A.melvin_gnu with 1 procs
+Finished SETUP for test SMS.f19_f19.A.melvin_gnu in 11.544286 seconds (PASS)
+Starting SHAREDLIB_BUILD for test SMS.f19_f19.A.melvin_gnu with 1 procs
+Finished SHAREDLIB_BUILD for test SMS.f19_f19.A.melvin_gnu in 82.670667 seconds (PASS)
+Starting MODEL_BUILD for test SMS.f19_f19.A.melvin_gnu with 4 procs
+Finished MODEL_BUILD for test SMS.f19_f19.A.melvin_gnu in 18.613263 seconds (PASS)
+Starting RUN for test SMS.f19_f19.A.melvin_gnu with 64 procs
+Finished RUN for test SMS.f19_f19.A.melvin_gnu in 35.068546 seconds (PASS). [COMPLETED 1 of 1]
+At test-scheduler close, state is:
+PASS SMS.f19_f19.A.melvin_gnu RUN
+ Case dir: /home/jgfouca/e3sm/scratch/SMS.f19_f19.A.melvin_gnu.20170504_163152_31aahy
+test-scheduler took 154.780044079 seconds
+
You can see that create_test informs the user of the case directory and of the progress and duration +of the various test phases.
+The $CASEDIR for the test will be created in $CIME_OUTPUT_ROOT. The name will be of the form:
+TESTTYPE[_MODIFIERS].GRID.COMPSET.MACHINE_COMPILER[.GROUP-TESTMODS].YYYYMMDD_HHMMSS_hash
+
If MODIFIERS or GROUP-TESTMODS are used, those will be included in the test output directory name. THe +extra string with YYYYMMDD_HHMMSS_hash is the testid and used to distinquish mulitple runs of the +same test. That string +can be replaced with the –test-id argument to create_test.
+For a test, the $CASEDIR will have $EXEROOT and $RUNDIR as subdirectories.
+The current state of a test is represented in the file $CASEDIR/TestStatus. Example output:
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel CREATE_NEWCASE
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel XML
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SETUP
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SHAREDLIB_BUILD time=277
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel MODEL_BUILD time=572
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SUBMIT
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel RUN time=208
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel COMPARE_base_rest
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel MEMLEAK insufficient data for memleak test
+PASS ERP_D_Ld3.ne4pg2_oQU480.F2010.chrysalis_intel SHORT_TERM_ARCHIVER
+
All other stdout output from the CIME case control system produced by running this test will +be put in the file $CASEDIR/TestStatus.log
+A cs.status.$testid script will also be put in the test root. This script will allow you to see the
+A big part of testing is managing your baselines (sometimes called gold results) and doing additional tests against +the baseline. The baseline for a test will be copy of the (history) files created in the run of the test.
+create_test can +be asked to perform bit-for-bit comparisons between the files generated by the current run of the test and +the files stored in the baseline. They must be bit-for-bit identical for the baseline test to pass.
+baseline testing adds an additional +test criteria to the one that comes from the test type and is used as a way to guard against unintentionaly +changing the results from a determinstic climate model.
+A baseline can be generated by passing -g
to create_test. There
+are additional options to control generating baselines.:
./scripts/create_test -b master -g SMS.ne30_f19_g16_rx1.A
+
Comparing the output of a test to a baseline is achieved by passing -c
to create_test.:
./scripts/create_test -b master -c SMS.ne30_f19_g16_rx1.A
+
Suppose you accidentally changed something in the source code that does not cause the model to crash but +does cause it to change the answers it produces. In this case, the SMS test would pass (it still runs) but the +comparison with baselines would FAIL (answers are not bit-for-bit identical to the baseline) and so the test +as a whole would FAIL.
+If you intended to change the answers, you need to update the baseline with new files. This is referred to +as “blessing” the test. +This is done with the bless_test_results tool. The tool provides the ability to bless different features of the baseline. The currently supported features are namelist files, history files, and performance metrics. The performance metrics are separated into throughput and memory usage.
+The following command can be used to compare a test to a baseline and bless an update to the history file.:
+./CIME/Tools/bless_test_results -b master --hist-only SMS.ne30_f19_g16_rx1.A
+
The compare_test_results <../Tools_user/compare_test_results.html>_ tool can be used to quickly compare tests to baselines and report any diffs.:
+./CIME/Tools/compare_test_results -b master SMS.ne30_f19_g16_rx1.A
+
By default performance baselines are generated by parsing the coupler log and comparing the throughput in SYPD (Simulated Years Per Day) and the memory usage high water.
+This can be customized by creating a python module under $DRIVER_ROOT/cime_config/customize
. There are four hooks that can be used to customize the generation and comparison.
perf_get_throughput
perf_get_memory
perf_compare_throughput_baseline
perf_compare_memory_baseline
The following pseudo code is an example of this customization.:
+# $DRIVER/cime_config/customize/perf_baseline.py
+
+def perf_get_throughput(case):
+ """
+ Parameters
+ ----------
+ case : CIME.case.case.Case
+ Current case object.
+
+ Returns
+ -------
+ str
+ Storing throughput value.
+ str
+ Open baseline file for writing.
+ """
+ current = analyze_throughput(...)
+
+ return json.dumps(current), "w"
+
+def perf_get_memory(case):
+ """
+ Parameters
+ ----------
+ case : CIME.case.case.Case
+ Current case object.
+
+ Returns
+ -------
+ str
+ Storing memory value.
+ str
+ Open baseline file for writing.
+ """
+ current = analyze_memory(case)
+
+ return json.dumps(current), "w"
+
+def perf_compare_throughput_baseline(case, baseline, tolerance):
+ """
+ Parameters
+ ----------
+ case : CIME.case.case.Case
+ Current case object.
+ baseline : str
+ Baseline throughput value.
+ tolerance : float
+ Allowed difference tolerance.
+
+ Returns
+ -------
+ bool
+ Whether throughput diff is below tolerance.
+ str
+ Comments about the results.
+ """
+ current = analyze_throughput(case)
+
+ baseline = json.loads(baseline)
+
+ diff, comments = generate_diff(...)
+
+ return diff, comments
+
+def perf_compare_memory_baseline(case, baseline, tolerance):
+ """
+ Parameters
+ ----------
+ case : CIME.case.case.Case
+ Current case object.
+ baseline : str
+ Baseline memory value.
+ tolerance : float
+ Allowed difference tolerance.
+
+ Returns
+ -------
+ bool
+ Whether memory diff is below tolerance.
+ str
+ Comments about the results.
+ """
+ current = analyze_memory(case)
+
+ baseline = json.loads(baseline)
+
+ diff, comments = generate_diff(...)
+
+ return diff, comments
+
CIME includes a copy of the General Purpose Timing Library (GPTL) and timers are placed throughout the CIME driver. CIME-driven models typically +also have GPTL timers in their code and very detailed timing information can be obtained.
+Every model run produces three types of timing output that you can examine:
+$CASEROOT/timing/$model_timing.$CASE.$datestamp
+This is the most useful way to quickly determine timing summaries across components +The following describes the most important parts of this timing file:
+An example timing file of this type is:
+---------------- TIMING PROFILE ---------------------
+Case : b.e20.BHIST.f09_g17.20thC.297_02
+LID : 9459679.chadmin1.180517-114852
+Machine : cheyenne
+Caseroot : /glade/p/cesmdata/cseg/runs/cesm2_0/b.e20.BHIST.f09_g17.20thC.297_02
+Timeroot : /glade/p/cesmdata/cseg/runs/cesm2_0/b.e20.BHIST.f09_g17.20thC.297_02/Tools
+User : hannay
+Curr Date : Thu May 17 12:42:27 2018
+grid : a%0.9x1.25_l%0.9x1.25_oi%gx1v7_r%r05_g%gland4_w%ww3a_m%gx1v7
+compset : HIST_CAM60_CLM50%BGC-CROP_CICE_POP2%ECO_MOSART_CISM2%NOEVOLVE_WW3_BGC%BDRD
+run_type : hybrid, continue_run = FALSE (inittype = TRUE)
+stop_option : nyears, stop_n = 1
+run_length : 365 days (364.958333333 for ocean)
+
+component comp_pes root_pe tasks x threads instances (stride)
+--------- ------ ------- ------ ------ --------- ------
+cpl = cpl 3456 0 1152 x 3 1 (1 )
+atm = cam 3456 0 1152 x 3 1 (1 )
+lnd = clm 2592 0 864 x 3 1 (1 )
+ice = cice 864 864 288 x 3 1 (1 )
+ocn = pop 768 1152 256 x 3 1 (1 )
+rof = mosart 2592 0 864 x 3 1 (1 )
+glc = cism 3456 0 1152 x 3 1 (1 )
+wav = ww 96 1408 32 x 3 1 (1 )
+esp = sesp 1 0 1 x 1 1 (1 )
+
+total pes active : 12960
+mpi tasks per node : 36
+pe count for cost estimate : 4320
+
+Overall Metrics:
+Model Cost: 3541.30 pe-hrs/simulated_year
+Model Throughput: 29.28 simulated_years/day
+
+Init Time : 242.045 seconds
+Run Time : 2951.082 seconds 8.085 seconds/day
+Final Time : 0.008 seconds
+
+Actual Ocn Init Wait Time : 768.737 seconds
+Estimated Ocn Init Run Time : 0.248 seconds
+Estimated Run Time Correction : 0.000 seconds
+ (This correction has been applied to the ocean and total run times)
+
+Runs Time in total seconds, seconds/model-day, and model-years/wall-day
+CPL Run Time represents time in CPL pes alone, not including time associated with data exchange with other components
+
+TOT Run Time: 2951.082 seconds 8.085 seconds/mday 29.28 myears/wday
+CPL Run Time: 248.696 seconds 0.681 seconds/mday 347.41 myears/wday
+ATM Run Time: 2097.788 seconds 5.747 seconds/mday 41.19 myears/wday
+LND Run Time: 545.991 seconds 1.496 seconds/mday 158.24 myears/wday
+ICE Run Time: 389.173 seconds 1.066 seconds/mday 222.01 myears/wday
+OCN Run Time: 2169.399 seconds 5.944 seconds/mday 39.83 myears/wday
+ROF Run Time: 42.241 seconds 0.116 seconds/mday 2045.41 myears/wday
+GLC Run Time: 1.049 seconds 0.003 seconds/mday 82364.16 myears/wday
+WAV Run Time: 517.414 seconds 1.418 seconds/mday 166.98 myears/wday
+ESP Run Time: 0.000 seconds 0.000 seconds/mday 0.00 myears/wday
+CPL COMM Time: 2464.660 seconds 6.752 seconds/mday 35.06 myears/wday
+
+---------------- DRIVER TIMING FLOWCHART ---------------------
+.............
+
TIMING PROFILE is the first section in the timing output. It +summarizes general timing information for the run. The total run +time and cost are given in several metrics to facilitate analysis +and comparisons with other runs. These metrics includ pe-hrs per +simulated year (cost), simulated years per wall day (thoughput), +seconds, and seconds per model day. The total run time for each +component and the time for initialization of the model also are +provided. These times are the aggregate over the total run and do +not take into account any temporal or processor load imbalances.
+DRIVER TIMING FLOWCHART is the second section in the timing +output. It provides timing information for the driver in +sequential order and indicates which processors are involved in +the cost. Finally, the timings for the coupler are broken out at +the bottom of the timing output file.
+$CASEROOT/timing/$model_timing_stats.$date
+Provides an overall detailed timing summary for each component, including the minimum and maximum of all the model timers.
+cpl.log.$datestamp
+Contains the run time for each model day during the run and is
+output during the run. You can search for tStamp
in the cpl.log
+file to see the information, which is useful for tracking down
+temporal variability in cost due to inherent model variability or
+to hardware. The model daily cost generally is pretty constant
+unless I/O is written intermittently, such as at the end of the
+month. This file will appear either in $RUNDIR or in
+DOUT_S_ROOT/logs for your run.
The xml variable CHECK_TIMING
, if set to TRUE
(the default) will produce the timing files in the $CASEROOT/timing directory.
User customization of timers is done via the xml variables TIMER_LEVEL
and TIMER_DETAIL
.
TIMER_LEVEL
:
This is the maximum code stack depth of enabled timers.
+TIMER_DETAIL
:
This is an integer indicating maximum detail level to profile. This +xml variable is used to set the namelist variable timing_detail_limit. +This namelist variable is used by perf_mod (in +$CIMEROOT/src/share/timing/perf_mod.F90) to turn timers off and on +depending on calls to the routine t_adj_detailf. If in the code a +statement appears like t_adj_detailf(+1), then the current timer +detail level is incremented by 1 and compared to the time_detail_limit +obtained from the namelist. If the limit is exceeded then the timer +is turned off.
+Further control of timers is then done via modifications of the prof_inparm namelists in the file drv_in. This is done
+via keyword-value settings in user_nl_cpl. As an example, if you want to set the namelist variable profile_barriers
to .true.
,
+add the following line in your $CASEROOT/user_nl_cpl:
profile_barriers = .true.
+
Overall Metrics:
+Model Cost: 327.14 pe-hrs/simulated_year (scale= 0.50)
+Model Throughput: 4.70 simulated_years/day
+
The model throughput is the estimated number of model years that you
+can run in a wallclock day. Based on this, you can maximize your queue
+limit and change $STOP_OPTION
and $STOP_N
.
For example, say a model’s throughput is 4.7 simulated_years/day, and
+the maximum runtime limit on your machine is 12 hours. 4.7 model
+years/24 hours * 12 hours = 2.35 years. On the massively parallel
+computers, there is always some variability in how long it will take
+a job to run. On some machines, you may need to leave as much as 20%
+buffer time in your run to guarantee that jobs finish reliably before
+the time limit. For that reason, set your model to run only one model
+year/job. In this example, set your wallclock at 12 hours and invoke
+xmlchange in CASEROOT
as shown here:
>./xmlchange STOP_OPTION=nyears
+>./xmlchange STOP_N=1
+>./xmlchange REST_OPTION=nyears
+>./xmlchange REST_N=1
+
Generally, create_newcase errors are reported to the terminal and should provide some guidance about what caused them.
+If create_newcase fails on a relatively generic error, first check to make sure the command-line arguments match the interface’s specification. See the help text to review usage.
+> create_newcase --help
+
If any of the python-based cime scripts are dying in a mysterious way, more information can be obtained by rerunning the script with the --debug
option.
Most problems associated with submission or launch are site-specific. +The batch and run aspects of the case.submit script are created by parsing the variables in $CASEROOT/env_batch.xml file.
+Take these steps to check for problems:
+Review the batch submission options in $CASEROOT/env_batch.xml. Confirm that they are consistent with the site-specific batch environment, and that the queue names, time limits, and hardware processor request make sense and are consistent with the case.
Make sure that case.submit uses the correct batch job tool for submitting the case.submit script. Depending on the batch environment, it might be bsub, qsub or another command. Also confirm if a redirection “<” character is required. The information for how case.submit submits jobs appears at the end of the standard output stream.
To see if a run completed successfully, check the last several lines of the cpl.log file for a string like SUCCESSFUL TERMINATION
. A successful job also usually copies the log files to the $CASEROOT/logs directory.
Check these things first when a job fails:
+Did the model time out?
Was a disk quota limit hit?
Did a machine go down?
Did a file system become full?
If any of those things happened, take appropriate corrective action (see suggestions below) and resubmit the job.
+If it is not clear that any of the above caused a case to fail, there are several places to look for error messages.
+Check component log files in your run directory ($RUNDIR
).
+This directory is set in the env_run.xml file.
+Each component writes its own log file, and there should be log files for every component in this format: cpl.log.yymmdd-hhmmss.
+Check each log file for an error message, especially at or near the end.
Check for a standard out and/or standard error file in $CASEROOT
.
+The standard out/err file often captures a significant amount of extra model output and also often contains significant system output when a job terminates.
+Useful error messages sometimes are found well above the bottom of a large standard out/err file. Backtrack from the bottom in search of an error message.
Check for core files in your run directory and review them using an appropriate tool.
Check any automated email from the job about why a job failed. Some sites’ batch schedulers send these.
Check the archive directory: $DOUT_S_ROOT/$CASE. If a case failed, the log files +or data may still have been archived.
Common errors
+One common error is for a job to time out, which often produces minimal error messages. +Review the daily model date stamps in the cpl.log file and the timestamps of files in your run directory to deduce the start and stop time of a run. +If the model was running fine, but the wallclock limit was reached, either reduce the run length or increase the wallclock setting.
+If the model hangs and then times out, that usually indicates an MPI or file system problem or possibly a model problem. If you suspect an intermittent system problem, try resubmitting the job. Also send a help request to local site consultants to provide them with feedback about system problems and to get help.
+Another error that can cause a timeout is a slow or intermittently slow node.
+The cpl.log file normally outputs the time used for every model simulation day. To review that data, grep the cpl.log file for the string tStamp
as shown here:
> grep tStamp cpl.log.* | more
+
The output looks like this:
+tStamp_write: model date = 10120 0 wall clock = 2009-09-28 09:10:46 avg dt = 58.58 dt = 58.18
+tStamp_write: model date = 10121 0 wall clock = 2009-09-28 09:12:32 avg dt = 60.10 dt = 105.90
+
Review the run times at the end of each line for each model day. +The “avg dt =” is the average time to simulate a model day and “dt = “ is the time needed to simulate the latest model day.
+The model date is printed in YYYYMMDD format and the wallclock is the local date and time. +In the example, 10120 is Jan 20, 0001, and the model took 58 seconds to run that day. +The next day, Jan 21, took 105.90 seconds.
+A wide variation in the simulation time for typical mid-month model days suggests a system problem. However, there are variations in the cost of the model over time. +For instance, on the last day of every simulated month, the model typically writes netcdf files, which can be a significant intermittent cost. +Also, some model configurations read data mid-month or run physics intermittently at a timestep longer than one day. +In those cases, some variability is expected. The time variation typically is quite erratic and unpredictable if the problem is system performance variability.
+Sometimes when a job times out or overflows disk space, the restart files will get mangled. +With the exception of the CAM and CLM history files, all the restart files have consistent sizes.
+Compare the restart files against the sizes of a previous restart. If they don’t match, remove them and move the previous restart into place before resubmitting the job. +See Restarting a run.
+It is not uncommon for nodes to fail on HPC systems or for access to large file systems to hang. Before you file a bug report, make sure a case fails consistently in the same place.
+Rerunning with additional debugging information
+There are a few changes you can make to your case to get additional information that aids in debugging:
+Increase the value of the run-time xml variable INFO_DBUG
: ./xmlchange INFO_DBUG=2
.
+This adds more information to the cpl.log file that can be useful if you can’t tell what component is aborting the run, or where bad coupling fields are originating.
+(This does NOT require rebuilding.)
Try rebuilding and rerunning with the build-time xml variable DEBUG
set to TRUE
: ./xmlchange DEBUG=TRUE
.
This adds various runtime checks that trap conditions such as out-of-bounds array indexing, divide by 0, and other floating point exceptions (the exact conditions checked depend on flags set in macros defined in the cmake_macros subdirectory of the caseroot).
The best way to do this is often to create a new case and run ./xmlchange DEBUG=TRUE
before running ./case.build
.
+However, if it is hard for you to recreate your case, then you can run that xmlchange command from your existing case; then you must run ./case.build --clean-all
before rerunning ./case.build
.
Note that the model will run significantly slower in this mode, so this may not be feasible if the model has to run a long time before producing the error. +(Sometimes it works well to run the model until shortly before the error in non-debug mode, have it write restart files, then restart after rebuilding in debug mode.) +Also note that answers will change slightly, so if the error arises from a rare condition, then it may not show up in this mode.
A unit test is a fast, self-verifying test of a small piece of code. +A single unit test typically covers 10s to 100s of lines of code; a single function or small module, for example. +It typically runs in milliseconds and produces a simple pass/fail result.
+Unit tests:
+Ensure that code remains correct as it is modified. In this respect, unit tests complement the CIME system tests.
Ensure that new code is correct.
Can help guide development, via test-driven development (TDD).
Provide executable documentation of the intended behavior of a piece of code.
Support development on your desktop machine.
CIME comes with a set of tools to support building and running unit tests. +These consist of:
+CMake tools to support building and running tests via CMake and CTest.
A Python script that provides a simple front end for the CMake-based tests.
The Fortran unit tests use pFUnit, which is a Fortran testing framework that follows conventions of other xUnit frameworks. CIME’s support for pFUnit requires pFUnit version 4 or greater.
+These instructions assume that you are using a machine that already has pFUnit installed, along with the necessary support in CIME. +If that is not the case, see How to add unit testing support on your machine.
+From the top-level CIME directory, you can run all of CIME’s Fortran unit tests by running:
+> scripts/fortran_unit_testing/run_tests.py --build-dir MY_BUILD_DIR
+
You can replace MY_BUILD_DIR
with a path to the directory where you would like the unit test build files to be placed.
+To ensure a completely clean build, use:
> scripts/fortran_unit_testing/run_tests.py --build-dir `mktemp -d ./unit_tests.XXXXXXXX`
+
Once you have built the unit tests (whether the build was successful or not), you can reuse the same build directory later to speed up the rebuild. +There are a number of useful arguments to run_tests.py. For full usage information, run:
+> scripts/fortran_unit_testing/run_tests.py --help
+
If your build is successful, you will get a message like this:
+==================================================
+Running CTest tests for __command_line_test__/__command_line_test__.
+==================================================
+
This will be followed by a list of tests, with a Pass/Fail message for each, like these examples:
+Test project /Users/sacks/cime/unit_tests.0XHUkfqL/__command_line_test__/__command_line_test__
+ Start 1: avect_wrapper
+ 1/17 Test #1: avect_wrapper .................... Passed 0.02 sec
+ Start 2: seq_map
+ 2/17 Test #2: seq_map .......................... Passed 0.01 sec
+ Start 3: glc_elevclass
+ 3/17 Test #3: glc_elevclass .................... Passed 0.01 sec
+
You will also see a final message like this:
+100% tests passed, 0 tests failed out of 17
+
These unit tests are run automatically as part of scripts_regression_tests on machines that have a serial build of pFUnit available for the default compiler.
+The following instructions assume that you have ported CIME to your +machine by following the instructions in +Porting and validating CIME on a new platform. If you have done that, you can add +unit testing support by building pFUnit on your machine and then +pointing to the build in your ** MACH*_*COMPILER.cmake** file. Those +processes are described in the following sections.
+Follow the instructions below to build pFUnit using the default compiler on your machine.
+That is the default for run_tests.py and that is required for scripts_regression_tests.py to run the unit tests on your machine.
+For the CMake step, we typically build with -DSKIP_MPI=YES
, -DSKIP_OPENMP=YES
and -DCMAKE_INSTALL_PREFIX
set to the directory where you want pFUnit to be installed.
+(At this time, no unit tests require parallel support, so we build without MPI support to keep things simple.)
+Optionally, you can also provide pFUnit builds with other supported compilers on your machine.
Obtain pFUnit from https://github.com/Goddard-Fortran-Ecosystem/pFUnit (see +https://github.com/Goddard-Fortran-Ecosystem/pFUnit#obtaining-pfunit for details)
Create a directory for the build and cd to that directory:
+> mkdir build-dir
+> cd build-dir
+
Set up your environment to be similar to the environment used in CIME system builds. +For example, load the appropriate compilers into your path. +An easy way to achieve this is to run the following with an optional compiler argument:
+> $CIMEROOT/CIME/scripts/configure --mpilib mpi-serial
+
Then source either ./.env_mach_specific.sh or ./.env_mach_specific.csh, depending on your shell.
+On some systems, you may need to explicitly set the FC
and CC
environment
+variables so that pFUnit’s CMake build picks up the correct compilers, e.g., with:
> export FC=ifort
+> export CC=icc
+
For convenience, set the PFUNIT
environment variable to point to the location where you want to install pFUnit. For example (in bash):
> export PFUNIT=$CESMDATAROOT/tools/pFUnit/pFUnit4.7.0_cheyenne_Intel19.1.1_noMPI_noOpenMP
+
Configure and build pFUnit:
+> cmake -DSKIP_MPI=YES -DSKIP_OPENMP=YES -DCMAKE_INSTALL_PREFIX=$PFUNIT ..
+> make -j 8
+
Run pFUnit’s self-tests:
+> make tests
+
Install pFUnit in the directory you specified earlier:
+> make install
+
You can repeat this process with different compiler environments.
+Make sure to choose a different installation directory for each build by setting the PFUNIT
variable differently.
After you build pFUnit, tell CIME about your build or builds.
+To do this, specify the appropriate path using the PFUNIT_PATH
CMake variable in the ** MACH*_*COMPILER.cmake** file.
+For a build with no MPI or openMP support (as recommended above), the block should look like this (with the actual path replaced with the PFUNIT path you specified when doing the build):
++++if (MPILIB STREQUAL mpi-serial AND NOT compile_threaded) + set(PFUNIT_PATH "$ENV{CESMDATAROOT}/tools/pFUnit/pFUnit4.7.0_cheyenne_Intel19.1.1_noMPI_noOpenMP") +endif() +
Once you have specified the path for your build(s), you should be able to run the unit tests by following the instructions in Running CIME’s Fortran unit tests.
+Todo
+Need to write this section. This will draw on some of the information in sections 3 and 4 of https://github.com/NCAR/cesm_unit_test_tutorial (though without the clm and cam stuff).
+It should also introduce the role of .pf files, which are referenced several paragraphs later as if already explained.
+Unit tests typically test a small piece of code, on the order of 10-100 lines, as in a single function or small class.
+Good unit tests are “FIRST”: +(https://pragprog.com/magazines/2012-01/unit-tests-are-first):
+Fast (milliseconds or less). This means that, generally, they should not do any file i/o. Also, if you are testing a complex function, test it with a simple set of inputs rather than a 10,000-element array that will require a few seconds of runtime to process.
Independent. This means that test Y shouldn’t depend on some global variable that text X created. Such dependencies cause problems if the tests run in a different order, if one test is dropped, and so on.
Repeatable. This means, for example, that you shouldn’t generate random numbers in your tests.
Self-verifying. Don’t write a test that writes out its answers for manual comparison. Tests should generate an automatic pass/fail result.
Timely. Write the tests before the production code (TDD) or immediately afterwards - not six months later when it’s time to finally merge your changes onto the trunk and you have forgotten the details. Much of the benefit of unit tests comes from developing them concurrently with the production code.
Good unit tests test a single, well-defined condition. This generally means that +you make a single call to the function or subroutine that you’re testing, with a +single set of inputs. Usually you need to run multiple tests in order to test +all of the unit’s possible behaviors.
+Testing a single condition in each test makes pinpointing problems easier when a test fails. +This also makes it easier to read and understand the tests, allowing them to serve as useful +documentation of how the code should operate.
+A good unit test has four distinct pieces:
+Setup: For example, creating variables that will be needed for the routine you’re testing. For simple tests, this piece may be empty.
Exercise: Calling the routine you’re testing.
Verify: Calling assertion methods (next section) to ensure that the results match what you expected.
Teardown: For example, deallocating variables. For simple tests, this piece may be empty. If it is needed, however, it is best done in the special tearDown routine discussed in Defining a test class in order to define setUp and tearDown methods and More on test teardown.**
If you have many tests of the same subroutine, you may find quite a
+lot of duplication. It’s good practice to extract major areas of duplication to their own
+subroutines in the .pf file, which your tests can call. This aids the understandability
+and maintainability of your tests. pFUnit knows which subroutines are tests and which are
+“helper” routines because of the @Test
directives: You only add a @Test
directive
+for your tests, not for your helper routines.
pFUnit provides many assertion methods that you can use in the Verify step. +Here are some of the most useful:
+
|
+Ensures that expected == actual.
+Accepts an optional |
+
|
+Ensures that expected < actual. |
+
|
+Ensures that expected > actual. |
+
|
++ |
|
++ |
|
+It is better to use the two-valued assertions above, if possible. +They provide more information if a test fails. |
+
|
++ |
|
+Ensures that the result is not NaN or infinity. |
+
|
+This can be useful for failure checking - for example, when your +function returns NaN to signal an error. |
+
Comparison assertions accept an optional tolerance
argument, which gives the
+tolerance for real-valued comparisons.
All of the assertion methods also accept an optional message
argument, which prints
+a string if the assertion fails. If no message is provided, you will be pointed to the
+file and line number of the failed assertion.
As noted in the comments in test_circle.pf, defining a test class is optional.
+However, defining a minimal test class as shown here with TestCircle
allows you
+use some pFUnit features such as the setUp and tearDown methods.
@TestCase
+type, extends(TestCase) :: TestCircle
+ contains
+ procedure :: setUp
+ procedure :: tearDown
+end type TestCircle
+
If you define this test class, you also need to:
+Define setUp and tearDown subroutines. These can start out empty:
+subroutine setUp(this)
+ class(TestCircle), intent(inout) :: this
+end subroutine setUp
+
+subroutine tearDown(this)
+ class(TestCircle), intent(inout) :: this
+end subroutine tearDown
+
Add an argument to each subroutine of the class. By convention, this argument is named this
.
Code in the setUp method is executed before each test. This is convenient +if you need to do some setup that is the same for every test.
+Code in the tearDown method is executed after each test. This is often used +to deallocate memory. See More on test teardown for details.
+You can add any data or procedures to the test class. Adding data is
+particularly useful, as this can be a way for the setUp and tearDown methods to
+interact with your tests: The setUp method can fill a class variable with data,
+which your tests can then use (accessed via this%somedata
). Conversely, if
+you want the tearDown method to deallocate a variable, the variable cannot be local
+to your test subroutine. Instead, you make the variable a member of the class, so
+that the tearDown method can access it.
Here is an example. Say you have this variable in your test class:
+real(r8), pointer :: somedata(:)
+
The setUp method can create somedata
if it needs to be the same
+for every test.
Alternatively, it can be created in each test routine that needs it if it +differs from test to test. (Some tests don’t need it at all.) In that situation, +create it like this:
+allocate(this%somedata(5))
+this%somedata(:) = [1,2,3,4,5]
+
Your tearDown method then can have code like this:
+if (associated(this%somedata)) then
+ deallocate(this%somedata)
+end if
+
As stated in Defining a test class in order to define setUp and tearDown methods, +code in the tearDown method is executed after each test, often to do cleanup operations.
+Using the tearDown method is recommended because tests abort if an assertion fails. +The tearDown method is still called, however, so teardown that needs to be done +still gets done, regardless of pass/fail status. Teardown code might otherwise be +skipped, which can lead other tests to fail or give unexpected results.
+All of the tests in a single test executable run one after another. For CIME, this +means all of the tests that are defined in all .pf files in a single test directory.
+As a result, tests can interact with each other if you don’t clean up after yourself. +In the best case, you might get a memory leak. In the worst case, the pass/fail status of tests +depends on which other tests have run previously, making your unit tests unrepeatable +and unreliable.
+To avoid this:
+Deallocate any pointers that your test allocates.
Reset any global variables to some known, initial state.
Do other, similar cleanup for resources that are shared by multiple tests.
In Fortran2003, allocatable variables are deallocated automatically when they go +out of scope, but pointers are not. Explicitly deallocate any pointers that have +been allocated, either in test setup or in the execution of the routine +you are testing.
+You might need to move some variables from subroutine-local to the class. This is +because the tearDown method can access class instance variables, but not subroutine-local +variables.
+CIME makes extensive use of global variables that may be used directly or +indirectly by a routine you are testing. If your test has allocated or modified +any global variables, it is important to reset them to their initial state in the +teardown portion of the test.
+There are many examples of unit tests in CIME, some simple and some quite complex. +You can find them by looking for files with the “.pf” extension:
+> find . --name '*.pf'
+
You can also see examples of the unit test build scripts by viewing the +CMakeLists.txt files throughout the source tree.
+Unfortunately, the documentation inside the pFUnit repository (in the documentation and Examples directories) is out-of-date (at least as of April, 2023): much of this documentation refers to version 3 of pFUnit, which differs in some ways from version 4. However, some working examples are provided in https://github.com/Goddard-Fortran-Ecosystem/pFUnit_demos.
+The CMake build infrastructure is in $CIMEROOT/CIME/non_py/src/CMake.
+The infrastructure for building and running tests with run_tests.py is in +$CIMEROOT/scripts/fortran_unit_testing. That directory also contains general +documentation about how to use the CIME unit test infrastructure (in the +README file) and examples (in the Examples directory).
+Currently, there are three kinds of workflow controls available in CIME.
+Multiple jobs workflow
+The file, $CIMEROOT/config/$model/machines/config_batch.xml, contains a section called <batch_jobs>
which defines the submit script templates and the pre-requisites for running them.
+As an example, in cesm, the default <batch_jobs>
section is the following, with an explanation give by the NOTES additions.
<batch_jobs>
+ <!-- order matters, with no-batch jobs will be run in the order listed here -->
+ <job name="case.run">
+ <template>template.case.run</template>
+ <prereq>$BUILD_COMPLETE and not $TEST</prereq>
+ </job>
+ <job name="case.test">
+ <template>template.case.test</template>
+ <prereq>$BUILD_COMPLETE and $TEST</prereq>
+ </job>
+ <job name="case.st_archive">
+ <template>template.st_archive</template>
+ <task_count>1</task_count>
+ <walltime>0:20:00</walltime>
+ <!-- If DOUT_S is true and case.run (or case.test) exits successfully then run st_archive-->
+ <dependency>case.run or case.test</dependency>
+ <prereq>$DOUT_S</prereq>
+ </job>
+</batch_jobs>
+
The elements that can be contained in the <batch_jobs>
section are:
<job name=”NAME”> : the name of the batch job.
Batch jobs can contain one or more jobs, and each job has the following elements:
+<template> : required, the associated template that is used to create the job.
<prepreq> : required, the pre-requiste settings of xml variables that determine whether the job will be run.
<task_count> : optional, the number of tasks the job should use.
<walltime> : optional, the maximum walltime the job should require.
<dependency> : optional, the previous job expected to complete before this job can start.
In the above the scripts for each <job>
entry,
+i.e. case.run
, case.test
and case.st_archive
are
+created from their respective templates the corresponding
+<template>
entry. The templates are located in the
+$CIMEROOT/config/$model/machines directory.
Furthermore, in the above case.run
will be run if the xml
+variables BUILD_COMPLETE
is true and TEST
is false. On the
+other hand, if BUILD_COMPLETE
is true and TEST
is true then
+case.test
will be run. In addition, if DOUT_S
is true,
+then case.st_archive
will be run after either case.run
+or case.test
successfully completes. Also note that
+case.st_archive
is a separate job that only requests a single
+task.
Users can extend the above workflow with their own custom needs.
+Pre-run and post-run script
+CIME provides the ability to execute user-defined scripts during
+the execution of case.run
. These user-defined scripts can be
+invoked either before and/or after the model is run. The xml variables that controls this capability are:
PRERUN_SCRIPT
: points to an external script to be run before model execution.
POSTRUN_SCRIPT
: points to an external script to be run after successful model completion.
Note, that when these scripts are called, the full processor allocation for the job will be used - even if only 1 processor actually is invoked for the external script.
+Data assimilation controls
++CIME provides the ability to hook in a data assimilation utility via a set of xml variables:
++
+- +
DATA_ASSIMILATION_SCRIPT
: points to an external script to be run after model completion- +
DATA_ASSIMILATION_CYCLES
: integer that controls the number of data assimilation cycles. The run script +will loop over these number of data assimilation cycles and for each cycle will run the model and subsequently run the data assimilation script.- +
+
DATA_ASSIMILATION
: if set to TRUE for a given component, then +a resume signal will be sent to that component at +initialization. If set, the component will execute special post +data assimilation logic on initialization. See the component +documentation for details. This flag is a bit subtle in that it is a per-component flag, not a model wide flag.++To see what the component flags are call + > ./xmlquery DATA_ASSIMILATION + +The output will look like + > DATA_ASSIMILATION: ['CPL:FALSE', 'ATM:TRUE', 'LND:FALSE', 'ICE:FALSE', 'OCN:FALSE', 'ROF:FALSE', 'GLC:FALSE', 'WAV:FALSE'] + + To change the LND value to TRUE issue + > ./xmlchange DATA_ASSIMILATION_LND=TRUE +
CIME (Common Infrastructure for Modeling the Earth, pronounced “SEAM”) primarily consists of a Case Control System that supports the configuration, compilation, execution, system testing and unit testing of an Earth System Model. The three main components of the Case Control System are:
+XML files that describe the available machines, models and model configurations.
Python scripts that take user commands and parse the XML files to configure a set of models with their +build and runtime options for a specified machine and the provide additional commands to build executables and +submit jobs.
Testing utilities to run defined system tests and report results for different configurations of the coupled system.
CIME also contains additional stand-alone tools useful for Earth system modeling including:
+Parallel regridding weight generation program
Scripts to automate off-line load-balancing.
Scripts to conduct ensemble-based statistical consistency tests.
Netcdf file comparison program (for bit-for-bit).
CIME does not contain the source code for any Earth System Model drivers or components. It is typically included alongside the source code of a host model. However, CIME does include pointers to external repositories that contain drivers, data models and other test components. These external components can be easily assembled to facilitate end-to-end system tests of the CIME infrastructure, which are defined in the CIME repository.
+CIME is developed in an open-source, public repository hosted under the Earth +System Model Computational Infrastructure (ESMCI) organization on +Github at http://github.com/ESMCI/cime.
+Atmosphere component XML files for data, stub, and dead components.
+Atmosphere data model, datm, XML files and settings.
+XML specification for archiving datm output files.
+XML variables and component descriptions specific to datm.
+XML namelist definitions for datm.
+The atmosphere stub model, satm, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to satm.
+The atmosphere dead model, xatm, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xatm.
+Component XML files in CIMEROOT/src sub-directories.
+Driver/Coupler XML files in CIMEROOT/src/drivers/mct/cime_config
+The Model Coupling Toolkit (MCT) based driver/coupler is +treated as a component by CIME with associated XML files +to define behavior.
+XML specification for archiving coupler output files.
+XML variables and component descriptions specific to the driver/coupler
+XML variables and component descriptions specific to the E3SM driver/coupler
+XML variables and component descriptions specific to the E3SM driver/coupler
+XML settings for driver/coupler defined component set (compset) configurations.
+XML settings for driver/coupler defined component set (compset) PE layouts.
+XML namelist definitions for the driver/coupler.
+XML namelist definitions for the driver/coupler fields.
+XML namelist definitions for the driver/coupler model input/output settings.
+External System Processing ESP component XML files for data, stub, and dead components.
+ESP data model, desp, XML files and settings.
+XML variables and component descriptions specific to desp.
+XML namelist definitions for desp.
+The ESP stub model, sesp, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to sesp.
+CIME includes a number of XML files used for configuration of a case. +General Users should never need to modify the XML files in the +CIMEROOT. Modifcations to XML settings is case specific and the tools +:ref:`xmlquery` and :ref:`xmlchange` in every CASEROOT can be used to query +and modify these settings while ensuring the continued schema +integrity of the XML.
+For advanced CIME developers, there are XML schema definition files +in the CIMEROOT/config/xml_schemas directory that can be used with +xmllint to verify the XML.
+ +Land component XML files for data, stub, and dead components.
+Land data model, dlnd, XML files and settings.
+XML specification for archiving dlnd output files.
+XML variables and component descriptions specific to dlnd.
+XML namelist definitions for dlnd.
+The land stub model, slnd, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to slnd.
+The land dead model, xlnd, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xlnd.
+Land ice component XML files for stub and dead components. +The land ice component does not currently have a data model.
+The land ice stub model, sglc, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to sglc.
+The land ice dead model, xglc, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xglc.
+Ocean component XML files for data, stub, and dead components.
+Ocean data model, docn, XML files and settings.
+XML specification for archiving docn output files.
+XML variables and component descriptions specific to docn.
+XML namelist definitions for docn.
+The ocean stub model, socn, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to socn.
+The ocean dead model, xocn, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xocn.
+River runoff component XML files for data, stub, and dead components.
+River runoff data model, drof, XML files and settings.
+XML specification for archiving drof output files.
+XML variables and component descriptions specific to drof.
+XML variables and component descriptions specific to drof.
+XML namelist definitions for drof.
+The river runoff stub model, srof, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to srof.
+The river runoff dead model, xrof, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xrof.
+Sea Ice component XML files for data, stub, and dead components.
+Sea Ice data model, dice, XML files and settings.
+XML specification for archiving dice output files.
+XML variables and component descriptions specific to dice.
+XML variables and component descriptions specific to dice.
+XML namelist definitions for dice.
+The sea ice stub model, sice, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to sice.
+The sea ice dead model, xice, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to satm.
+Wave component XML files for data, stub, and dead components.
+Wave data model, dwav, XML files and settings.
+XML specification for archiving dwav output files.
+XML variables and component descriptions specific to dwav.
+XML variables and component descriptions specific to dwav.
+XML namelist definitions for dwav.
+The wave stub model, swav, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to swav.
+The wave dead model, xwav, does not output any files in the RUNDIR nor +does it have any namelist settings.
+XML variables and component descriptions specific to xwav.
+