diff --git a/config/acme/machines/config_machines.xml b/config/acme/machines/config_machines.xml
index e8289956938..c4db3bbbef2 100644
--- a/config/acme/machines/config_machines.xml
+++ b/config/acme/machines/config_machines.xml
@@ -1126,16 +1126,11 @@
/usr/bin/runjob
- --label short
-
- --ranks-per-node $PES_PER_NODE
-
- --np $TOTALPES
- --block $COBALT_PARTNAME $LOCARGS
- --envs BG_THREADLAYOUT=1
- --envs XL_BG_SPREADLAYOUT=YES
- --envs OMP_STACKSIZE=64M
- --envs OMP_NUM_THREADS=$ENV{OMP_NUM_THREADS}
+ --label short
+ --ranks-per-node $PES_PER_NODE
+ --np $TOTALPES
+ --block $COBALT_PARTNAME $LOCARGS
+ $ENV{BGQ_SMP_VARS}
@@ -1152,8 +1147,10 @@
10000
- FALSE
- 64M
+
+
+
+ --envs BG_THREADLAYOUT=1 XL_BG_SPREADLAYOUT=YES OMP_DYNAMIC=FALSE OMP_STACKSIZE=64M OMP_NUM_THREADS=$ENV{OMP_NUM_THREADS}
@@ -1289,16 +1286,11 @@
/usr/bin/runjob
- --label short
-
- --ranks-per-node $PES_PER_NODE
-
- --np $TOTALPES
- --block $COBALT_PARTNAME $LOCARGS
- --envs BG_THREADLAYOUT=1
- --envs XL_BG_SPREADLAYOUT=YES
- --envs OMP_STACKSIZE=64M
- --envs OMP_NUM_THREADS=$ENV{OMP_NUM_THREADS}
+ --label short
+ --ranks-per-node $PES_PER_NODE
+ --np $TOTALPES
+ --block $COBALT_PARTNAME $LOCARGS
+ $ENV{BGQ_SMP_VARS}
@@ -1315,8 +1307,10 @@
10000
- FALSE
- 64M
+
+
+
+ --envs BG_THREADLAYOUT=1 XL_BG_SPREADLAYOUT=YES OMP_DYNAMIC=FALSE OMP_STACKSIZE=64M OMP_NUM_THREADS=$ENV{OMP_NUM_THREADS}
diff --git a/config/config_tests.xml b/config/config_tests.xml
index 6bef57899c7..edf0455d323 100644
--- a/config/config_tests.xml
+++ b/config/config_tests.xml
@@ -245,6 +245,7 @@ NODEFAIL Tests restart upon detected node failure. Generates fake failu
ndays
11
FALSE
+ TRUE
diff --git a/scripts/Tools/preview_run b/scripts/Tools/preview_run
index eca424d052a..56d8c3fe726 100755
--- a/scripts/Tools/preview_run
+++ b/scripts/Tools/preview_run
@@ -58,6 +58,7 @@ def _main_func(description):
with Case(caseroot, read_only=False) as case:
print "BATCH SUBMIT:"
+ case.load_env()
job = "case.test" if case.get_value("TEST") else "case.run"
job_id_to_cmd = case.submit_jobs(dry_run=True, job=job)
for job_id, cmd in job_id_to_cmd:
diff --git a/scripts/fortran_unit_testing/run_tests.py b/scripts/fortran_unit_testing/run_tests.py
index 9ce19b2d453..6d9c0d772dd 100755
--- a/scripts/fortran_unit_testing/run_tests.py
+++ b/scripts/fortran_unit_testing/run_tests.py
@@ -7,7 +7,7 @@
sys.path.append(os.path.join(_CIMEROOT, "scripts", "fortran_unit_testing", "python"))
from standard_script_setup import *
-from CIME.BuildTools.configure import configure
+from CIME.BuildTools.configure import configure, FakeCase
from CIME.utils import run_cmd_no_fail, stringify_bool, expect
from CIME.XML.machines import Machines
from CIME.XML.compilers import Compilers
@@ -318,7 +318,8 @@ def _main():
unit_testing=True)
machspecific = EnvMachSpecific(build_dir, unit_testing=True)
- machspecific.load_env(compiler, debug, mpilib)
+ fake_case = FakeCase(compiler, mpilib, debug)
+ machspecific.load_env(fake_case)
os.environ["OS"] = os_
os.environ["COMPILER"] = compiler
os.environ["DEBUG"] = stringify_bool(debug)
diff --git a/scripts/lib/CIME/BuildTools/configure.py b/scripts/lib/CIME/BuildTools/configure.py
index 26281117df6..392468f7d8e 100644
--- a/scripts/lib/CIME/BuildTools/configure.py
+++ b/scripts/lib/CIME/BuildTools/configure.py
@@ -66,6 +66,14 @@ def _copy_depends_files(machine_name, machines_dir, output_dir, compiler):
if os.path.isfile(dfile) and not os.path.isfile(outputdfile):
shutil.copyfile(dfile, outputdfile)
+class FakeCase(object):
+
+ def __init__(self, compiler, mpilib, debug):
+ self._vals = {"COMPILER":compiler, "MPILIB":mpilib, "DEBUG":debug}
+
+ def get_value(self, attrib):
+ expect(attrib in self._vals, "FakeCase does not support getting value of '%s'" % attrib)
+ return self._vals[attrib]
def _generate_env_mach_specific(output_dir, machobj, compiler, mpilib, debug,
sysos, unit_testing):
@@ -79,8 +87,9 @@ def _generate_env_mach_specific(output_dir, machobj, compiler, mpilib, debug,
ems_file = EnvMachSpecific(output_dir, unit_testing=unit_testing)
ems_file.populate(machobj)
ems_file.write()
+ fake_case = FakeCase(compiler, mpilib, debug)
for shell in ('sh', 'csh'):
- ems_file.make_env_mach_specific_file(compiler, debug, mpilib, shell)
+ ems_file.make_env_mach_specific_file(shell, fake_case)
shell_path = os.path.join(output_dir, ".env_mach_specific." + shell)
with open(shell_path, 'a') as shell_file:
if shell == 'sh':
diff --git a/scripts/lib/CIME/SystemTests/erp.py b/scripts/lib/CIME/SystemTests/erp.py
index 5e0dc748b45..bebbba7e295 100644
--- a/scripts/lib/CIME/SystemTests/erp.py
+++ b/scripts/lib/CIME/SystemTests/erp.py
@@ -31,7 +31,6 @@ def build_phase(self, sharedlib_only=False, model_only=False):
and tasks. This test will fail for components (e.g. pop) that do not reproduce exactly
with different numbers of mpi tasks.
"""
- self._case.set_value("BUILD_THREADED",True)
if sharedlib_only:
return self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only)
@@ -52,6 +51,8 @@ def build_phase(self, sharedlib_only=False, model_only=False):
if is_locked(envbuild1):
restore(envbuild1, newname="env_build.xml")
+ self._case.read_xml()
+
# Build two executables, one using the original tasks and threads (ERP1) and
# one using the modified tasks and threads (ERP2)
# The reason we currently need two executables that CESM-CICE has a compile time decomposition
@@ -132,6 +133,8 @@ def run_phase(self):
self._case.set_value("CONTINUE_RUN", True)
self._case.set_value("REST_OPTION","never")
suffix = "rest"
+
self.run_indv(suffix=suffix)
+ self._case.flush()
self._component_compare_test("base", "rest")
diff --git a/scripts/lib/CIME/XML/env_mach_specific.py b/scripts/lib/CIME/XML/env_mach_specific.py
index 14083b7354d..a9cfb707a21 100644
--- a/scripts/lib/CIME/XML/env_mach_specific.py
+++ b/scripts/lib/CIME/XML/env_mach_specific.py
@@ -53,34 +53,34 @@ def populate(self, machobj):
for node in nodes:
self.add_child(node)
- def _get_modules_for_case(self, compiler, debug, mpilib):
+ def _get_modules_for_case(self, case):
module_nodes = self.get_nodes("modules")
modules_to_load = None
if module_nodes is not None:
- modules_to_load = self._compute_module_actions(module_nodes, compiler, debug, mpilib)
+ modules_to_load = self._compute_module_actions(module_nodes, case)
return modules_to_load
- def _get_envs_for_case(self, compiler, debug, mpilib):
+ def _get_envs_for_case(self, case):
env_nodes = self.get_nodes("environment_variables")
envs_to_set = None
if env_nodes is not None:
- envs_to_set = self._compute_env_actions(env_nodes, compiler, debug, mpilib)
+ envs_to_set = self._compute_env_actions(env_nodes, case)
return envs_to_set
- def load_env(self, compiler, debug, mpilib):
+ def load_env(self, case):
"""
Should only be called by case.load_env
"""
# Do the modules so we can refer to env vars set by the modules
# in the environment_variables block
- modules_to_load = self._get_modules_for_case(compiler, debug, mpilib)
+ modules_to_load = self._get_modules_for_case(case)
if (modules_to_load is not None):
self.load_modules(modules_to_load)
- envs_to_set = self._get_envs_for_case(compiler, debug, mpilib)
+ envs_to_set = self._get_envs_for_case(case)
if (envs_to_set is not None):
self.load_envs(envs_to_set)
@@ -130,9 +130,9 @@ def save_all_env_info(self, filename):
f.write(self.list_modules())
run_cmd_no_fail("echo -e '\n' && env", arg_stdout=filename)
- def make_env_mach_specific_file(self, compiler, debug, mpilib, shell):
- modules_to_load = self._get_modules_for_case(compiler, debug, mpilib)
- envs_to_set = self._get_envs_for_case(compiler, debug, mpilib)
+ def make_env_mach_specific_file(self, shell, case):
+ modules_to_load = self._get_modules_for_case(case)
+ envs_to_set = self._get_envs_for_case(case)
filename = ".env_mach_specific.%s" % shell
lines = []
if modules_to_load is not None:
@@ -152,24 +152,25 @@ def make_env_mach_specific_file(self, compiler, debug, mpilib, shell):
def load_envs(self, envs_to_set):
for env_name, env_value in envs_to_set:
- os.environ[env_name] = env_value
+ os.environ[env_name] = "" if env_value is None else env_value
# Private API
- def _compute_module_actions(self, module_nodes, compiler, debug, mpilib):
- return self._compute_actions(module_nodes, "command", compiler, debug, mpilib)
+ def _compute_module_actions(self, module_nodes, case):
+ return self._compute_actions(module_nodes, "command", case)
- def _compute_env_actions(self, env_nodes, compiler, debug, mpilib):
- return self._compute_actions(env_nodes, "env", compiler, debug, mpilib)
+ def _compute_env_actions(self, env_nodes, case):
+ return self._compute_actions(env_nodes, "env", case)
- def _compute_actions(self, nodes, child_tag, compiler, debug, mpilib):
+ def _compute_actions(self, nodes, child_tag, case):
result = [] # list of tuples ("name", "argument")
+ compiler, mpilib = case.get_value("COMPILER"), case.get_value("MPILIB")
for node in nodes:
- if (self._match_attribs(node.attrib, compiler, debug, mpilib)):
+ if (self._match_attribs(node.attrib, case)):
for child in node:
expect(child.tag == child_tag, "Expected %s element" % child_tag)
- if (self._match_attribs(child.attrib, compiler, debug, mpilib)):
+ if (self._match_attribs(child.attrib, case)):
val = child.text
if val is not None:
# We allow a couple special substitutions for these fields
@@ -178,36 +179,39 @@ def _compute_actions(self, nodes, child_tag, compiler, debug, mpilib):
val = self.get_resolved_value(val)
expect("$" not in val, "Not safe to leave unresolved items in env var value: '%s'" % val)
+
# intentional unindent, result is appended even if val is None
result.append( (child.get("name"), val) )
return result
- def _match_attribs(self, attribs, compiler, debug, mpilib):
- if ("compiler" in attribs and
- not self._match(compiler, attribs["compiler"])):
- return False
- elif ("mpilib" in attribs and
- not self._match(mpilib, attribs["mpilib"])):
- return False
- elif ("debug" in attribs and
- not self._match("TRUE" if debug else "FALSE", attribs["debug"].upper())):
- return False
- elif ("unit_testing" in attribs and
- not self._match("TRUE" if self._unit_testing else "FALSE",
- attribs["unit_testing"].upper())):
- return False
+ def _match_attribs(self, attribs, case):
+ # check for matches with case-vars
+ for attrib in attribs:
+ if attrib == "unit_testing": # special case
+ if not self._match(self._unit_testing, attribs["unit_testing"].upper()):
+ return False
+ elif attrib == "name":
+ pass
+ else:
+ val = case.get_value(attrib.upper())
+ expect(val is not None, "Cannot match attrib '%s', case has no value for it" % attrib.upper())
+ if not self._match(val, attribs[attrib]):
+ return False
return True
def _match(self, my_value, xml_value):
- if (xml_value.startswith("!")):
+ if xml_value.startswith("!"):
result = my_value != xml_value[1:]
+ elif isinstance(my_value, bool):
+ if my_value: result = xml_value == "TRUE"
+ else: result = xml_value == "FALSE"
else:
result = my_value == xml_value
- logger.debug("(env_mach_specific) _match %s %s %s"%(my_value, xml_value, result))
- return result
+ logger.debug("(env_mach_specific) _match %s %s %s" % (my_value, xml_value, result))
+ return result
def _get_module_commands(self, modules_to_load, shell):
# Note this is independent of module system type
diff --git a/scripts/lib/CIME/XML/generic_xml.py b/scripts/lib/CIME/XML/generic_xml.py
index 717e4b17bdd..43a31160425 100644
--- a/scripts/lib/CIME/XML/generic_xml.py
+++ b/scripts/lib/CIME/XML/generic_xml.py
@@ -4,7 +4,6 @@
"""
from CIME.XML.standard_module_setup import *
from distutils.spawn import find_executable
-from xml.dom import minidom
import getpass
@@ -47,11 +46,12 @@ def read(self, infile, schema=None):
Read and parse an xml file into the object
"""
logger.debug("read: " + infile)
- if self.tree:
- self.root.append(ET.parse(infile).getroot())
- else:
- self.tree = ET.parse(infile)
- self.root = self.tree.getroot()
+ with open(infile, 'r') as fd:
+ if self.tree:
+ self.root.append(ET.parse(fd).getroot())
+ else:
+ self.tree = ET.parse(fd)
+ self.root = self.tree.getroot()
if schema is not None and self.get_version() > 1.0:
self.validate_xml_file(infile, schema)
@@ -79,9 +79,8 @@ def write(self, outfile=None):
if xmllint is not None:
run_cmd_no_fail("%s --format --output %s -"%(xmllint,outfile), input_str=xmlstr)
else:
- doc = minidom.parseString(xmlstr)
with open(outfile,'w') as xmlout:
- doc.writexml(xmlout,addindent=' ')
+ xmlout.write(xmlstr)
def get_node(self, nodename, attributes=None, root=None, xpath=None):
"""
diff --git a/scripts/lib/CIME/build.py b/scripts/lib/CIME/build.py
index 111c629f742..9b7e5ff8932 100644
--- a/scripts/lib/CIME/build.py
+++ b/scripts/lib/CIME/build.py
@@ -267,7 +267,6 @@ def _build_libraries(case, exeroot, sharedpath, caseroot, cimeroot, libroot, lid
if re.search("Current setting for", line):
logger.warn(line)
-
# clm not a shared lib for ACME
if get_model() != "acme":
comp_lnd = case.get_value("COMP_LND")
@@ -520,7 +519,6 @@ def _case_build_impl(caseroot, case, sharedlib_only, model_only):
logs.extend(_build_model(build_threaded, exeroot, clm_config_opts, incroot, complist,
lid, caseroot, cimeroot, compiler))
- if not sharedlib_only:
# in case component build scripts updated the xml files, update the case object
case.read_xml()
post_build(case, logs)
diff --git a/scripts/lib/CIME/case.py b/scripts/lib/CIME/case.py
index 15ec0f83171..81ac7911a3e 100644
--- a/scripts/lib/CIME/case.py
+++ b/scripts/lib/CIME/case.py
@@ -149,6 +149,8 @@ def initialize_derived_attributes(self):
"unit_testing" : False
}
+ os.environ["OMP_NUM_THREADS"] = str(self.thread_count)
+
executable = env_mach_spec.get_mpirun(self, mpi_attribs, job="case.run", exe_only=True)[0]
if executable is not None and "aprun" in executable:
self.num_nodes = get_aprun_cmd_for_case(self, "acme.exe")[1]
@@ -177,11 +179,8 @@ def schedule_rewrite(self, env_file):
self._env_files_that_need_rewrite.add(env_file)
def read_xml(self):
- if(len(self._env_files_that_need_rewrite)>0):
- files = ""
- for env_file in self._env_files_that_need_rewrite:
- files += " "+env_file.filename
- expect(False,"Object(s) %s seem to have newer data than the corresponding case file"%files)
+ if self._env_files_that_need_rewrite:
+ expect(False, "Object(s) %s seem to have newer data than the corresponding case file" % " ".join([env_file.filename for env_file in self._env_files_that_need_rewrite]))
self._env_entryid_files = []
self._env_entryid_files.append(EnvCase(self._caseroot, components=None))
@@ -1168,11 +1167,8 @@ def set_model_version(self, model):
def load_env(self):
if not self._is_env_loaded:
- compiler = self.get_value("COMPILER")
- debug=self.get_value("DEBUG")
- mpilib=self.get_value("MPILIB")
env_module = self.get_env("mach_specific")
- env_module.load_env(compiler=compiler,debug=debug, mpilib=mpilib)
+ env_module.load_env(self)
self._is_env_loaded = True
def get_build_threaded(self):
@@ -1180,7 +1176,8 @@ def get_build_threaded(self):
Returns True if current settings require a threaded build/run.
"""
force_threaded = self.get_value("BUILD_THREADED")
- return bool(force_threaded) or self.thread_count > 1
+ smp_present = bool(force_threaded) or self.thread_count > 1
+ return smp_present
def _check_testlists(self, compset_alias, grid_name, files):
"""
@@ -1213,6 +1210,8 @@ def set_file(self, xmlfile):
gfile = GenericXML(infile=xmlfile)
ftype = gfile.get_id()
+ self.flush(flushall=True)
+
logger.warn("setting case file to %s"%xmlfile)
new_env_file = None
for env_file in self._env_entryid_files:
diff --git a/scripts/lib/CIME/case_setup.py b/scripts/lib/CIME/case_setup.py
index a4e158d7116..45157c58a9b 100644
--- a/scripts/lib/CIME/case_setup.py
+++ b/scripts/lib/CIME/case_setup.py
@@ -141,6 +141,8 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
case.initialize_derived_attributes()
+ case.set_value("SMP_PRESENT", case.get_build_threaded())
+
# Set TOTAL_CORES
case.set_value("TOTAL_CORES", case.total_tasks * case.cores_per_task )
else:
@@ -163,6 +165,8 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
case.initialize_derived_attributes()
+ case.set_value("SMP_PRESENT", case.get_build_threaded())
+
# create batch files
logger.info("Creating batch script case.run")
env_batch = case.get_env("batch")
@@ -212,8 +216,8 @@ def _case_setup_impl(case, caseroot, clean=False, test_mode=False, reset=False):
# Record env information
env_module = case.get_env("mach_specific")
- env_module.make_env_mach_specific_file(compiler, debug, mpilib, "sh")
- env_module.make_env_mach_specific_file(compiler, debug, mpilib, "csh")
+ env_module.make_env_mach_specific_file("sh", case)
+ env_module.make_env_mach_specific_file("csh", case)
env_module.save_all_env_info("software_environment.txt")
###############################################################################
diff --git a/scripts/lib/CIME/utils.py b/scripts/lib/CIME/utils.py
index 57a28addbe3..06cf1e14dc2 100644
--- a/scripts/lib/CIME/utils.py
+++ b/scripts/lib/CIME/utils.py
@@ -1243,7 +1243,7 @@ def _check_for_invalid_args(args):
if arg.startswith("-") and len(arg) > 2:
# Uncomment these lines when we want to enforce --mulitchararg syntax
# if arg == "-value" or arg == "-noecho":
- logger.warn("This argument is depricated, please use -%s"%arg)
+ logger.warn("This argument is depricated, please use -%s"%arg)
# else:
# expect(False, "Invalid argument %s\n Multi-character arguments should begin with \"--\" and single character with \"-\"\n Use --help for a complete list of available options"%arg)
diff --git a/src/drivers/mct/cime_config/config_component.xml b/src/drivers/mct/cime_config/config_component.xml
index b6a872f7d7c..68756483368 100644
--- a/src/drivers/mct/cime_config/config_component.xml
+++ b/src/drivers/mct/cime_config/config_component.xml
@@ -761,6 +761,15 @@
If TRUE, the component libraries are always built with OpenMP capability.
+
+ logical
+ TRUE,FALSE
+ FALSE
+ build_def
+ env_build.xml
+ TRUE implies that at least one of the components is built threaded (DO NOT EDIT)
+
+
logical
TRUE,FALSE