Repository: terrapower/armi
Pull request #1149 (2023-02-03 15:58:24)

Pointing the Component.density method at 3D material density
## Description

Presumably by accident, in the past the `Component.density()` method pointed at the 2D/linear expansion-only/pseudodensity, instead of the usual physical density of materials.  This PR corrects that issue.

@opotowsky 
**NOTE**: In testing, however, I found no materials in ARMI that explicitly defined separate `pseduodensity()` and `density()` method. So, using existing materials I could make a unit test that would fail after the change. But the moment I mocked up a material with clearly different `density` and `pseudodensity`, the test immediately failed.

---

## Checklist

- [X] This PR has only one purpose or idea.
- [X] Tests have been added/updated to verify that the new/changed code works.

<!-- 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/release/index.html) (location `doc/release/0.X.rst`) are up-to-date with any bug fixes or new features.
- [X] The documentation is still up-to-date in the `doc` folder.
- [X] The dependencies are still up-to-date in `setup.py`.



Patch:
diff --git a/armi/materials/uraniumOxide.py b/armi/materials/uraniumOxide.py
index f1219c21..3f164b16 100644
--- a/armi/materials/uraniumOxide.py
+++ b/armi/materials/uraniumOxide.py
@@ -55,7 +55,7 @@ class UraniumOxide(material.FuelMaterial, material.SimpleSolid):
     propertyUnits = {"heat capacity": "J/mol-K"}
 
     propertyValidTemperature = {
-        "density": ((300, 3100), "K"),
+        "density3": ((300, 3100), "K"),
         "heat capacity": ((298.15, 3120), "K"),
         "linear expansion": ((273, 3120), "K"),
         "linear expansion percent": ((273, __meltingPoint), "K"),
@@ -166,7 +166,7 @@ class UraniumOxide(material.FuelMaterial, material.SimpleSolid):
         Polynomial line fit to data from [#ornltm2000]_ on page 11.
         """
         Tk = getTk(Tc, Tk)
-        self.checkPropertyTempRange("density", Tk)
+        self.checkPropertyTempRange("density3", Tk)
 
         return (-1.01147e-7 * Tk ** 2 - 1.29933e-4 * Tk + 1.09805e1) * self.getTD()
 
diff --git a/armi/reactor/components/component.py b/armi/reactor/components/component.py
index f9c5138f..51472d6c 100644
--- a/armi/reactor/components/component.py
+++ b/armi/reactor/components/component.py
@@ -1165,7 +1165,7 @@ class Component(composites.Composite, metaclass=ComponentType):
 
         if not density:
             # possible that there are no nuclides in this component yet. In that case, defer to Material.
-            density = self.material.density(Tc=self.temperatureInC)
+            density = self.material.density3(Tc=self.temperatureInC)
 
         return density
 
diff --git a/armi/runLog.py b/armi/runLog.py
index 9d70cc8d..d2216a50 100644
--- a/armi/runLog.py
+++ b/armi/runLog.py
@@ -383,23 +383,23 @@ def raw(msg):
     """
     Print raw text without any special functionality.
     """
-    LOG.log("header", msg, single=False, label=msg)
+    LOG.log("header", msg, single=False)
 
 
 def extra(msg, single=False, label=None):
-    LOG.log("extra", msg, single=single, label=label)
+    LOG.log("extra", msg, single=single)
 
 
 def debug(msg, single=False, label=None):
-    LOG.log("debug", msg, single=single, label=label)
+    LOG.log("debug", msg, single=single)
 
 
 def info(msg, single=False, label=None):
-    LOG.log("info", msg, single=single, label=label)
+    LOG.log("info", msg, single=single)
 
 
 def important(msg, single=False, label=None):
-    LOG.log("important", msg, single=single, label=label)
+    LOG.log("important", msg, single=single)
 
 
 def warning(msg, single=False, label=None):
@@ -446,18 +446,23 @@ class DeduplicationFilter(logging.Filter):
         # determine if this is a "do not duplicate" message
         msg = str(record.msg)
         single = getattr(record, "single", False)
-        label = getattr(record, "label", msg)
-        label = msg if label is None else label
 
         # If the message is set to "do not duplicate" we may filter it out
         if single:
             if record.levelno in (logging.WARNING, logging.CRITICAL):
+                # if this is from the custom logger, it will have a "label"
+                label = getattr(record, "label", msg)
+                # the "label" default is None, which needs to be replaced
+                label = msg if label is None else label
+
                 if label not in self.singleWarningMessageCounts:
                     self.singleWarningMessageCounts[label] = 1
                 else:
                     self.singleWarningMessageCounts[label] += 1
                     return False
             else:
+                # in sub-warning cases, hash the msg, for a faster label lookup
+                label = hash(msg)
                 if label not in self.singleMessageCounts:
                     self.singleMessageCounts[label] = 1
                 else:
diff --git a/doc/release/0.2.rst b/doc/release/0.2.rst
index da725644..3ff30547 100644
--- a/doc/release/0.2.rst
+++ b/doc/release/0.2.rst
@@ -32,6 +32,7 @@ What's new in ARMI
 #. Bug fix for Magnessium density curve. (`PR#1126 https://github.com/terrapower/armi/pull/1126`_)
 #. Bug fix for Potassium density curve. (`PR#1128 https://github.com/terrapower/armi/pull/1128`_)
 #. Bug fix for Concrete density curve. (`PR#1131 https://github.com/terrapower/armi/pull/1131`_)
+#. Bug fix for Component.density. (`PR#1149 https://github.com/terrapower/armi/pull/1149`_)
 #. Calculate block kgHM and kgFis on core loading and after shuffling. (`PR#1136 https://github.com/terrapower/armi/pull/1136`_)
 
 Bug fixes


Test patch:
diff --git a/armi/reactor/tests/test_components.py b/armi/reactor/tests/test_components.py
index cdfe98fd..c6cf9c97 100644
--- a/armi/reactor/tests/test_components.py
+++ b/armi/reactor/tests/test_components.py
@@ -20,6 +20,7 @@ import copy
 import math
 import unittest
 
+from armi.materials.material import Material
 from armi.reactor import components
 from armi.reactor.components import (
     Component,
@@ -326,6 +327,31 @@ class TestShapedComponent(TestGeneralComponents):
             c.getArea() * c.parent.getHeight() * c.density(), self.component.getMass()
         )
 
+    def test_density3D(self):
+        """Testing the Component density gets the correct 3D material density."""
+
+        class StrangeMaterial(Material):
+            """material designed to make the test easier to understand"""
+
+            def density(self, Tk=None, Tc=None):
+                return 1.0
+
+            def density3(self, Tk=None, Tc=None):
+                return 3.0
+
+        c = Sphere(
+            name="strangeBall",
+            material=StrangeMaterial(),
+            Tinput=200,
+            Thot=500,
+            od=1,
+            id=0,
+            mult=1,
+        )
+
+        # we expect to see the 3D material density here
+        self.assertEqual(c.density(), 3.0)
+
 
 class TestDerivedShape(TestShapedComponent):
     componentCls = DerivedShape