Repository: terrapower/armi
Pull request #1958 (2024-10-17 16:40:28)

Updating cluster settings
## What is the change?

* Removing the setting `mpiTasksPerNode`
* Renaming `numProcessors` to `nTasks`

## Why is the change being made?

Updating terminology to something more modern.

---

## Checklist

- [x] This PR has only [one purpose or idea](https://terrapower.github.io/armi/developer/tooling.html#one-idea-one-pr).
- [x] [Tests](https://terrapower.github.io/armi/developer/tooling.html#test-it) have been added/updated to verify any new/changed code.

<!-- Check the code quality -->

- [x] The code style follows [good practices](https://terrapower.github.io/armi/developer/standards_and_practices.html).
- [x] The commit message(s) follow [good practices](https://terrapower.github.io/armi/developer/tooling.html).

<!-- Check the project-level cruft -->

- [x] The [release notes](https://terrapower.github.io/armi/developer/tooling.html#add-release-notes) have been updated if necessary.
- [x] The [documentation](https://terrapower.github.io/armi/developer/tooling.html#document-it) is still up-to-date in the `doc` folder.
- [x] The dependencies are still up-to-date in `pyproject.toml`.

CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/terrapower/armi?pullRequest=1958) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our [Contributor License Agreement](https://cla-assistant.io/terrapower/armi?pullRequest=1958) before we can accept your contribution.<br/>**0** out of **2** committers have signed the CLA.<br/><br/>:x: Bharat Medasani<br/>:x: mbk-tp<br/><hr/>**Bharat Medasani** seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please [add the email address used for this commit to your account](https://help.github.com/articles/why-are-my-commits-linked-to-the-wrong-user/#commits-are-not-linked-to-any-user).<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/terrapower/armi?pullRequest=1958) it.</sub>
john-science: Can you add a release not here: https://github.com/terrapower/armi/blob/main/doc/release/0.4.rst?plain=1#L42

It should says "Renaming numProcessors to nTasks".

Patch:
diff --git a/.gitignore b/.gitignore
index e64adfe9..b301d4cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ coverage_results.*
 dist-*/
 dist/
 doc/_build
+doc/anl-afci-177
 doc/gallery
 doc/gallery-src/framework/*.yaml
 doc/tutorials/anl-afci-177*
diff --git a/armi/bookkeeping/report/newReportUtils.py b/armi/bookkeeping/report/newReportUtils.py
index a4fd7f68..98c14bf9 100644
--- a/armi/bookkeeping/report/newReportUtils.py
+++ b/armi/bookkeeping/report/newReportUtils.py
@@ -426,7 +426,7 @@ def insertSettingsData(cs, report):
         "burnSteps",
         "skipCycles",
         "cycleLength",
-        "numProcessors",
+        "nTasks",
     ]:
         report[COMPREHENSIVE_REPORT][CASE_PARAMETERS].addRow([key, cs[key]])
 
diff --git a/armi/cli/modify.py b/armi/cli/modify.py
index 75c557a5..197f9f8b 100644
--- a/armi/cli/modify.py
+++ b/armi/cli/modify.py
@@ -30,7 +30,7 @@ class ModifyCaseSettingsCommand(EntryPoint):
 
     Run the entry point like this::
 
-        $ python -m armi modify --numProcessors=3 *.yaml
+        $ python -m armi modify --nTasks=3 *.yaml
 
     """
 
diff --git a/armi/settings/fwSettings/globalSettings.py b/armi/settings/fwSettings/globalSettings.py
index 3b114388..43eb9209 100644
--- a/armi/settings/fwSettings/globalSettings.py
+++ b/armi/settings/fwSettings/globalSettings.py
@@ -80,10 +80,9 @@ CONF_LOW_POWER_REGION_FRACTION = "lowPowerRegionFraction"  # reports
 CONF_MATERIAL_NAMESPACE_ORDER = "materialNamespaceOrder"
 CONF_MIN_MESH_SIZE_RATIO = "minMeshSizeRatio"
 CONF_MODULE_VERBOSITY = "moduleVerbosity"
-CONF_MPI_TASKS_PER_NODE = "mpiTasksPerNode"
 CONF_N_CYCLES = "nCycles"
 CONF_NON_UNIFORM_ASSEM_FLAGS = "nonUniformAssemFlags"
-CONF_NUM_PROCESSORS = "numProcessors"
+CONF_N_TASKS = "nTasks"
 CONF_OPERATOR_LOCATION = "operatorLocation"
 CONF_OUTPUT_CACHE_LOCATION = "outputCacheLocation"
 CONF_OUTPUT_FILE_EXTENSION = "outputFileExtension"
@@ -154,11 +153,12 @@ def defineSettings() -> List[setting.Setting]:
     """
     settings = [
         setting.Setting(
-            CONF_NUM_PROCESSORS,
+            CONF_N_TASKS,
             default=1,
-            label="CPUs",
-            description="Number of CPUs to request on the cluster",
+            label="parallel tasks",
+            description="Number of parallel tasks to request on the cluster",
             schema=vol.All(vol.Coerce(int), vol.Range(min=1)),
+            oldNames=[("numProcessors", None)],
         ),
         setting.Setting(
             CONF_INITIALIZE_BURN_CHAIN,
@@ -587,14 +587,6 @@ def defineSettings() -> List[setting.Setting]:
             description="Description needed",
             schema=vol.All(vol.Coerce(float), vol.Range(min=0, max=1)),
         ),
-        setting.Setting(
-            CONF_MPI_TASKS_PER_NODE,
-            default=0,
-            label="MPI Tasks per Node",
-            description="Number of independent processes that are allocated to each "
-            "cluster node. 0 means 1 process per CPU.",
-            schema=vol.All(vol.Coerce(int), vol.Range(min=0)),
-        ),
         setting.Setting(
             CONF_N_CYCLES,
             default=1,
diff --git a/doc/conf.py b/doc/conf.py
index 58f84a76..d21b56a8 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -231,17 +231,22 @@ def autodoc_skip_member_handler(app, what, name, obj, skip, options):
 def setup(app):
     """Method to make `make html` generate api documentation."""
     app.connect("autodoc-skip-member", autodoc_skip_member_handler)
-
     app.add_domain(PatchedPythonDomain, override=True)
-
     app.add_directive("exec", ExecDirective)
     app.add_directive("pyreverse", PyReverse)
+    app.add_directive("impl", directives.admonitions.Note)
+    app.add_directive("test", directives.admonitions.Note)
 
-    # copy resources needed to build the tutorial notebooks. nbsphinx_link is slick, but
-    # the working directory for running the notebooks is the directory of the link
-    # itself, so relative paths don't work.
+    # making tutorial data dir
+    dataDir = pathlib.Path("user") / ".." / "anl-afci-177"
+    if not os.path.exists(dataDir):
+        os.mkdir(dataDir)
+
+    # copy resources needed to build the tutorial notebooks. nbsphinx_link is slick, but the working
+    # directory for running the notebooks is the directory of the link itself, so relative paths
+    # don't work.
     for path in _TUTORIAL_FILES:
-        shutil.copy(path, pathlib.Path("user") / "tutorials")
+        shutil.copy(path, dataDir)
 
 
 # If extensions (or modules to document with autodoc) are in another directory,
@@ -251,36 +256,36 @@ sys.path.insert(0, os.path.abspath(".."))
 
 # -- General configuration -----------------------------------------------------
 
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+# Add any Sphinx extension module names here, as strings. They can be extensions coming with Sphinx
+# (named 'sphinx.ext.*') or your custom ones.
 extensions = [
+    "nbsphinx",
+    "nbsphinx_link",
     "sphinx.ext.autodoc",
-    "sphinx.ext.napoleon",
     "sphinx.ext.autosummary",
     "sphinx.ext.doctest",
-    "sphinx.ext.todo",
-    "sphinx.ext.mathjax",
+    "sphinx.ext.extlinks",
     "sphinx.ext.ifconfig",
+    "sphinx.ext.imgconverter",  # to convert GH Actions badge SVGs to PNG for LaTeX
     "sphinx.ext.inheritance_diagram",
-    "sphinx.ext.extlinks",
-    "sphinx.ext.viewcode",
     "sphinx.ext.intersphinx",
-    "sphinxcontrib.apidoc",
-    "nbsphinx",
-    "nbsphinx_link",
-    "sphinxext.opengraph",
+    "sphinx.ext.mathjax",
+    "sphinx.ext.napoleon",
+    "sphinx.ext.todo",
+    "sphinx.ext.viewcode",
     "sphinx_gallery.gen_gallery",
-    "sphinx.ext.imgconverter",  # to convert GH Actions badge SVGs to PNG for LaTeX
-    "sphinxcontrib.plantuml",
     "sphinx_rtd_theme",  # needed here for loading jquery in sphinx 6
+    "sphinxcontrib.apidoc",
     "sphinxcontrib.jquery",  # see https://github.com/readthedocs/sphinx_rtd_theme/issues/1452
+    "sphinxcontrib.plantuml",
+    "sphinxext.opengraph",
 ]
 
 # Our API should make sense without documenting private/special members.
 autodoc_default_options = {
     "members": True,
-    "undoc-members": True,
     "private-members": False,
+    "undoc-members": True,
 }
 autodoc_member_order = "bysource"
 # this line removes huge numbers of false and misleading, inherited docstrings
diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst
index c5d52338..ea65d6de 100644
--- a/doc/release/0.4.rst
+++ b/doc/release/0.4.rst
@@ -40,6 +40,7 @@ API Changes
 #. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 <https://github.com/terrapower/armi/1846>`_)
 #. Transposing ``pinMgFluxes`` parameters so that leading dimension is pin index (`PR#1937 <https://github.com/terrapower/armi/pull/1937>`)
 #. Removing ``globalFluxInterface.DoseResultsMapper`` class (`PR#1952 <https://github.com/terrapower/armi/pull/1952>`)
+#. Removing setting ``mpiTasksPerNode`` and renaming ``numProcessors`` to ``nTasks``. (`PR#1958 <https://github.com/terrapower/armi/pull/1958>`_)
 #. TBD
 
 Bug Fixes


Test patch:
diff --git a/armi/bookkeeping/db/tests/test_database3.py b/armi/bookkeeping/db/tests/test_database3.py
index 9a413da5..4e5c8381 100644
--- a/armi/bookkeeping/db/tests/test_database3.py
+++ b/armi/bookkeeping/db/tests/test_database3.py
@@ -535,7 +535,7 @@ class TestDatabase3Smaller(unittest.TestCase):
 
     def test_loadCS(self):
         cs = self.db.loadCS()
-        self.assertEqual(cs["numProcessors"], 1)
+        self.assertEqual(cs["nTasks"], 1)
         self.assertEqual(cs["nCycles"], 2)
 
     def test_loadBlueprints(self):
diff --git a/armi/cli/tests/test_runEntryPoint.py b/armi/cli/tests/test_runEntryPoint.py
index b0e541d6..9ba20f07 100644
--- a/armi/cli/tests/test_runEntryPoint.py
+++ b/armi/cli/tests/test_runEntryPoint.py
@@ -369,15 +369,15 @@ class TestModifyCaseSettingsCommand(unittest.TestCase):
             for fileName in ["armiRun.yaml", "refSmallReactor.yaml"]:
                 copyfile(os.path.join(TEST_ROOT, fileName), fileName)
 
-            # pass in --numProcessors=333
-            mcs.parse_args(["--numProcessors=333", "--rootDir", ".", "armiRun.yaml"])
+            # pass in --nTasks=333
+            mcs.parse_args(["--nTasks=333", "--rootDir", ".", "armiRun.yaml"])
 
             # invoke the CLI
             mcs.invoke()
 
-            # validate the change to numProcessors was made
+            # validate the change to nTasks was made
             txt = open("armiRun.yaml", "r").read()
-            self.assertIn("numProcessors: 333", txt)
+            self.assertIn("nTasks: 333", txt)
 
 
 class TestReportsEntryPoint(unittest.TestCase):
diff --git a/armi/settings/fwSettings/tests/test_fwSettings.py b/armi/settings/fwSettings/tests/test_fwSettings.py
index 724a6f4d..06537268 100644
--- a/armi/settings/fwSettings/tests/test_fwSettings.py
+++ b/armi/settings/fwSettings/tests/test_fwSettings.py
@@ -26,7 +26,7 @@ class TestSchema(unittest.TestCase):
     def setUp(self):
         self.cs = caseSettings.Settings()
         self.settings = {
-            "numProcessors": {
+            "nTasks": {
                 "valid": 1,
                 "invalid": -1,
                 "error": vol.error.MultipleInvalid,
@@ -91,11 +91,6 @@ class TestSchema(unittest.TestCase):
                 "invalid": 2,
                 "error": vol.error.MultipleInvalid,
             },
-            "mpiTasksPerNode": {
-                "valid": 0,
-                "invalid": -1,
-                "error": vol.error.MultipleInvalid,
-            },
             "nCycles": {"valid": 1, "invalid": -1, "error": vol.error.MultipleInvalid},
             "power": {"valid": 0, "invalid": -1, "error": vol.error.MultipleInvalid},
             "skipCycles": {
diff --git a/armi/settings/tests/test_inspectors.py b/armi/settings/tests/test_inspectors.py
index fe636175..cb27b3e9 100644
--- a/armi/settings/tests/test_inspectors.py
+++ b/armi/settings/tests/test_inspectors.py
@@ -152,10 +152,10 @@ class TestInspector(unittest.TestCase):
         self.assertIn("nCycles", keys)
 
     def test_createQueryRevertBadPathToDefault(self):
-        query = createQueryRevertBadPathToDefault(self.inspector, "numProcessors")
+        query = createQueryRevertBadPathToDefault(self.inspector, "nTasks")
         self.assertEqual(
             str(query),
-            "<Query: Setting numProcessors points to a nonexistent location:\n1>",
+            "<Query: Setting nTasks points to a nonexistent location:\n1>",
         )
 
     def test_correctCyclesToZeroBurnup(self):
diff --git a/armi/settings/tests/test_settings.py b/armi/settings/tests/test_settings.py
index 4deeb9d8..3cfae738 100644
--- a/armi/settings/tests/test_settings.py
+++ b/armi/settings/tests/test_settings.py
@@ -324,7 +324,7 @@ assemblyRotationAlgorithm: buReducingAssemblyRotatoin
         # some default settings values
         for sett in ["availabilityFactor", "db"]:
             self.assertIn(sett, settingsList)
-        self.assertNotIn("numProcessors", settingsList)
+        self.assertNotIn("nTasks", settingsList)
 
     def test_setModuleVerbosities(self):
         # init settings and use them to set module-level logging levels
diff --git a/armi/settings/tests/test_settingsIO.py b/armi/settings/tests/test_settingsIO.py
index 36dd7237..9b99f1b3 100644
--- a/armi/settings/tests/test_settingsIO.py
+++ b/armi/settings/tests/test_settingsIO.py
@@ -63,7 +63,7 @@ class SettingsReaderTests(unittest.TestCase):
     def test_basicSettingsReader(self):
         reader = settingsIO.SettingsReader(self.cs)
 
-        self.assertEqual(reader["numProcessors"], 1)
+        self.assertEqual(reader["nTasks"], 1)
         self.assertEqual(reader["nCycles"], 1)
 
         self.assertFalse(getattr(reader, "filelessBP"))
@@ -165,7 +165,7 @@ class SettingsWriterTests(unittest.TestCase):
         self.cs.loadFromInputFile(self.filepathYaml)
         txt = open(self.filepathYaml, "r").read()
         self.assertIn("nCycles: 55", txt)
-        self.assertNotIn("numProcessors", txt)
+        self.assertNotIn("nTasks", txt)
 
     def test_writeMedium(self):
         """Setting output as a sparse file that only includes defaults if they are
@@ -173,10 +173,10 @@ class SettingsWriterTests(unittest.TestCase):
         """
         with open(self.filepathYaml, "w") as stream:
             # Specify a setting that is also a default
-            self.cs.writeToYamlStream(stream, "medium", ["numProcessors"])
+            self.cs.writeToYamlStream(stream, "medium", ["nTasks"])
         txt = open(self.filepathYaml, "r").read()
         self.assertIn("nCycles: 55", txt)
-        self.assertIn("numProcessors: 1", txt)
+        self.assertIn("nTasks: 1", txt)
 
     def test_writeFull(self):
         """Setting output as a full, all defaults included file.
@@ -189,7 +189,7 @@ class SettingsWriterTests(unittest.TestCase):
         txt = open(self.filepathYaml, "r").read()
         self.assertIn("nCycles: 55", txt)
         # check a default setting
-        self.assertIn("numProcessors: 1", txt)
+        self.assertIn("nTasks: 1", txt)
 
     def test_writeYaml(self):
         self.cs.writeToYamlFile(self.filepathYaml)
diff --git a/armi/tests/test_apps.py b/armi/tests/test_apps.py
index a6b6ea7e..c14ffe5a 100644
--- a/armi/tests/test_apps.py
+++ b/armi/tests/test_apps.py
@@ -165,7 +165,7 @@ class TestApps(unittest.TestCase):
         settings = app.getSettings()
 
         self.assertGreater(len(settings), 100)
-        self.assertEqual(settings["numProcessors"].value, 1)
+        self.assertEqual(settings["nTasks"].value, 1)
         self.assertEqual(settings["nCycles"].value, 1)
 
     def test_splashText(self):