From 7b258d456f49633bf2109f9376f89ee3466a1543 Mon Sep 17 00:00:00 2001 From: jakehader Date: Wed, 14 Aug 2024 08:19:45 -0700 Subject: [PATCH 01/18] Strawman fix for the custom isotopics for testing. --- armi/reactor/blueprints/blockBlueprint.py | 2 +- armi/reactor/blueprints/componentBlueprint.py | 54 +++++++++++++++---- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/armi/reactor/blueprints/blockBlueprint.py b/armi/reactor/blueprints/blockBlueprint.py index f233fd58a..18113834e 100644 --- a/armi/reactor/blueprints/blockBlueprint.py +++ b/armi/reactor/blueprints/blockBlueprint.py @@ -145,7 +145,7 @@ def construct( filteredMaterialInput, byComponentMatModKeys = self._filterMaterialInput( materialInput, componentDesign ) - c = componentDesign.construct(blueprint, filteredMaterialInput) + c = componentDesign.construct(cs, blueprint, filteredMaterialInput) components[c.name] = c # check that the mat mods for this component are valid options diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index f6b85228e..37e5a7c47 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -27,6 +27,7 @@ from armi.reactor.flags import Flags from armi.utils import densityTools from armi.nucDirectory import nuclideBases +from armi.settings.fwSettings.globalSettings import CONF_INPUT_HEIGHTS_HOT COMPONENT_GROUP_SHAPE = "group" @@ -186,7 +187,7 @@ def shape(self, shape): mergeWith = yamlize.Attribute(type=str, default=None) area = yamlize.Attribute(type=float, default=None) - def construct(self, blueprint, matMods): + def construct(self, cs, blueprint, matMods): """Construct a component or group. .. impl:: User-defined on material alterations are applied here. @@ -205,6 +206,17 @@ def construct(self, blueprint, matMods): The ``applyInputParams()`` method of that material class is then called, passing in the associated material modifications data, which the material class can then use to modify the isotopics as necessary. + + Parameters + ---------- + cs : Settings + Settings object for the appropriate simulation. + + blueprint : Blueprints + Blueprints object containing various detailed information, such as nuclides to model + + matMods : dict + Material modifications to apply to the component. """ runLog.debug("Constructing component {}".format(self.name)) kwargs = self._conformKwargs(blueprint, matMods) @@ -225,13 +237,13 @@ class can then use to modify the isotopics as necessary. constructedObject = components.factory(shape, [], kwargs) _setComponentFlags(constructedObject, self.flags, blueprint) insertDepletableNuclideKeys(constructedObject, blueprint) - - # set the custom density for non-custom material components after construction - self.setCustomDensity(constructedObject, blueprint, matMods) + + self._setComponentCustomDensity(constructedObject, blueprint, matMods, + blockHeightsConsideredHot=cs[CONF_INPUT_HEIGHTS_HOT]) return constructedObject - - def setCustomDensity(self, constructedComponent, blueprint, matMods): + + def _setComponentCustomDensity(self, comp, blueprint, matMods, blockHeightsConsideredHot): """Apply a custom density to a material with custom isotopics but not a 'custom material'.""" if self.isotopics is None: # No custom isotopics specified @@ -247,7 +259,7 @@ def setCustomDensity(self, constructedComponent, blueprint, matMods): "A zero or negative density was specified in a custom isotopics input. " "This is not permitted, if a 0 density material is needed, use 'Void'. " "The component is {} and the isotopics entry is {}.".format( - constructedComponent, self.isotopics + comp, self.isotopics ) ) raise ValueError( @@ -275,13 +287,33 @@ def setCustomDensity(self, constructedComponent, blueprint, matMods): "Cannot apply custom densities to materials without density." ) - densityRatio = density / constructedComponent.density() - constructedComponent.changeNDensByFactor(densityRatio) - + # Apply a density scaling to account for the temperature change between the input + # temperature `Tinput` and the hot temperature `Thot`. There may be a better place to + # in the initialization to determine if the block height will be interpreted as hot dimensions + # already. + # + # - Apply additional density scaling when the component is added to a block? + # - Apply here? Not great since this requires a case settings to be applied or some pre-knowledge + # of where the component is going to live? + dLL = comp.material.linearExpansionFactor(Tc=comp.temperatureInC, T0=comp.inputTemperatureInC) + if blockHeightsConsideredHot: + f = 1.0 / (1 + dLL) ** 2 + else: + f = 1.0 / (1 + dLL) ** 3 + + print(comp.density()) + print(f) + print(comp.inputTemperatureInC) + print(comp.temperatureInC) + scaledDensity = comp.density() / f + densityRatio = density / scaledDensity + comp.changeNDensByFactor(densityRatio) + print(comp.density()) + runLog.important( "A custom material density was specified in the custom isotopics for non-custom " "material {}. The component density has been altered to " - "{}.".format(mat, constructedComponent.density()), + "{} at temperature {} C".format(mat, scaledDensity, comp.temperatureInC), single=True, ) From 1290e146af796e9bf763dd61de330e9dff2a0763 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 14:47:23 -0600 Subject: [PATCH 02/18] Remove print statements and fix black formatting --- armi/reactor/blueprints/componentBlueprint.py | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index c27014810..703c119b4 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -206,15 +206,15 @@ def construct(self, cs, blueprint, matMods): The ``applyInputParams()`` method of that material class is then called, passing in the associated material modifications data, which the material class can then use to modify the isotopics as necessary. - + Parameters ---------- cs : Settings Settings object for the appropriate simulation. - + blueprint : Blueprints Blueprints object containing various detailed information, such as nuclides to model - + matMods : dict Material modifications to apply to the component. """ @@ -236,19 +236,25 @@ class can then use to modify the isotopics as necessary. else: constructedObject = components.factory(shape, [], kwargs) _setComponentFlags(constructedObject, self.flags, blueprint) - insertDepletableNuclideKeys(constructedObject, blueprint) + insertDepletableNuclideKeys(constructedObject, blueprint) constructedObject.p.theoreticalDensityFrac = ( constructedObject.material.getTD() ) - self._setComponentCustomDensity(constructedObject, blueprint, matMods, - blockHeightsConsideredHot=cs[CONF_INPUT_HEIGHTS_HOT]) + self._setComponentCustomDensity( + constructedObject, + blueprint, + matMods, + blockHeightsConsideredHot=cs[CONF_INPUT_HEIGHTS_HOT], + ) # set the custom density for non-custom material components after construction self.setCustomDensity(constructedObject, blueprint, matMods) return constructedObject - - def _setComponentCustomDensity(self, comp, blueprint, matMods, blockHeightsConsideredHot): + + def _setComponentCustomDensity( + self, comp, blueprint, matMods, blockHeightsConsideredHot + ): """Apply a custom density to a material with custom isotopics but not a 'custom material'.""" if self.isotopics is None: # No custom isotopics specified @@ -295,30 +301,29 @@ def _setComponentCustomDensity(self, comp, blueprint, matMods, blockHeightsConsi # Apply a density scaling to account for the temperature change between the input # temperature `Tinput` and the hot temperature `Thot`. There may be a better place to # in the initialization to determine if the block height will be interpreted as hot dimensions - # already. + # already. # - # - Apply additional density scaling when the component is added to a block? + # - Apply additional density scaling when the component is added to a block? # - Apply here? Not great since this requires a case settings to be applied or some pre-knowledge # of where the component is going to live? - dLL = comp.material.linearExpansionFactor(Tc=comp.temperatureInC, T0=comp.inputTemperatureInC) + dLL = comp.material.linearExpansionFactor( + Tc=comp.temperatureInC, T0=comp.inputTemperatureInC + ) if blockHeightsConsideredHot: f = 1.0 / (1 + dLL) ** 2 else: f = 1.0 / (1 + dLL) ** 3 - - print(comp.density()) - print(f) - print(comp.inputTemperatureInC) - print(comp.temperatureInC) + scaledDensity = comp.density() / f densityRatio = density / scaledDensity comp.changeNDensByFactor(densityRatio) - print(comp.density()) - + runLog.important( "A custom material density was specified in the custom isotopics for non-custom " "material {}. The component density has been altered to " - "{} at temperature {} C".format(mat, scaledDensity, comp.temperatureInC), + "{} at temperature {} C".format( + mat, scaledDensity, comp.temperatureInC + ), single=True, ) From fd831caddf9ba189e54b820b064fd6e10bd263d9 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 15:02:12 -0600 Subject: [PATCH 03/18] Fix improperly resolved merge conflict --- armi/reactor/blueprints/componentBlueprint.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index 703c119b4..334652572 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -247,8 +247,6 @@ class can then use to modify the isotopics as necessary. matMods, blockHeightsConsideredHot=cs[CONF_INPUT_HEIGHTS_HOT], ) - # set the custom density for non-custom material components after construction - self.setCustomDensity(constructedObject, blueprint, matMods) return constructedObject From 895e61b7a66799f2456eeaed3981d441e6a85bc9 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 16:52:58 -0600 Subject: [PATCH 04/18] Refactor some runLog prints --- armi/reactor/blueprints/componentBlueprint.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index 334652572..8ca9e1fb8 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -267,9 +267,7 @@ def _setComponentCustomDensity( runLog.error( "A zero or negative density was specified in a custom isotopics input. " "This is not permitted, if a 0 density material is needed, use 'Void'. " - "The component is {} and the isotopics entry is {}.".format( - comp, self.isotopics - ) + f"The component is {comp} and the isotopics entry is {self.isotopics}." ) raise ValueError( "A zero or negative density was specified in the custom isotopics for a component" @@ -286,11 +284,9 @@ def _setComponentCustomDensity( ) if not mat.density(Tc=self.Tinput) > 0: runLog.error( - "A custom density has been assigned to material '{}', which has no baseline " + f"A custom density has been assigned to material '{self.material}', which has no baseline " "density. Only materials with a starting density may be assigned a density. " - "This comes up e.g. if isotopics are assigned to 'Void'.".format( - self.material - ) + "This comes up e.g. if isotopics are assigned to 'Void'." ) raise ValueError( "Cannot apply custom densities to materials without density." @@ -318,10 +314,8 @@ def _setComponentCustomDensity( runLog.important( "A custom material density was specified in the custom isotopics for non-custom " - "material {}. The component density has been altered to " - "{} at temperature {} C".format( - mat, scaledDensity, comp.temperatureInC - ), + f"material {mat}. The component density has been altered to " + f"{scaledDensity} at temperature {comp.temperatureInC} C", single=True, ) From db06fd48a4d6a54911fd074bc8d51b152d79f1b8 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 16:53:32 -0600 Subject: [PATCH 05/18] Add some TODOs for reviewers to think about --- armi/reactor/blueprints/componentBlueprint.py | 2 ++ armi/reactor/blueprints/isotopicOptions.py | 1 + 2 files changed, 3 insertions(+) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index 8ca9e1fb8..25e0ee601 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -312,6 +312,8 @@ def _setComponentCustomDensity( densityRatio = density / scaledDensity comp.changeNDensByFactor(densityRatio) + # TODO the density in this print is broken after #1852, see + # https://github.com/terrapower/armi/blob/8b9a693f9bc4030eaa3fbcaa394bb7af74ed10bf/armi/reactor/components/component.py#L1332-L1344 runLog.important( "A custom material density was specified in the custom isotopics for non-custom " f"material {mat}. The component density has been altered to " diff --git a/armi/reactor/blueprints/isotopicOptions.py b/armi/reactor/blueprints/isotopicOptions.py index 37ded7621..6bbd3710c 100644 --- a/armi/reactor/blueprints/isotopicOptions.py +++ b/armi/reactor/blueprints/isotopicOptions.py @@ -394,6 +394,7 @@ def apply(self, material): material.massFrac = dict(self.massFracs) if self.density is not None: if not isinstance(material, materials.Custom): + # TODO I think this warning should go away? runLog.important( "A custom density or number densities has been specified for non-custom " "material {}. The material object's density will not be updated to prevent unintentional " From 55d8c13a66402a687a28a222066105262084fd2b Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 17:05:53 -0600 Subject: [PATCH 06/18] Pass in the correct recursive args) --- armi/reactor/blueprints/componentBlueprint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index 25e0ee601..f1a05aac6 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -226,7 +226,7 @@ class can then use to modify the isotopics as necessary. constructedObject = composites.Composite(self.name) for groupedComponent in group: componentDesign = blueprint.componentDesigns[groupedComponent.name] - component = componentDesign.construct(blueprint, matMods=dict()) + component = componentDesign.construct(cs, blueprint, matMods=dict()) # override free component multiplicity if it's set based on the group definition component.setDimension("mult", groupedComponent.mult) _setComponentFlags(component, self.flags, blueprint) From 396508290b000fea8a9a2838f841e49393ce1cab Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sat, 30 Nov 2024 17:21:22 -0600 Subject: [PATCH 07/18] Fix test --- armi/reactor/blueprints/tests/test_blueprints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armi/reactor/blueprints/tests/test_blueprints.py b/armi/reactor/blueprints/tests/test_blueprints.py index d63c12467..51e291d4f 100644 --- a/armi/reactor/blueprints/tests/test_blueprints.py +++ b/armi/reactor/blueprints/tests/test_blueprints.py @@ -612,7 +612,7 @@ def test_topLevelComponentInput(self): # which is required during construction of a component design._resolveNuclides(cs) componentDesign = design.componentDesigns["freefuel"] - topComponent = componentDesign.construct(design, matMods=dict()) + topComponent = componentDesign.construct(cs, design, matMods=dict()) self.assertEqual(topComponent.getDimension("od", cold=True), 4.0) self.assertGreater(topComponent.getVolume(), 0.0) self.assertGreater(topComponent.getMass("U235"), 0.0) From d97853394bbba72ebfee334c620ccfad9d0002f4 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:16:17 -0600 Subject: [PATCH 08/18] Fix unit tests that were broken from the start --- .../blueprints/tests/test_customIsotopics.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/armi/reactor/blueprints/tests/test_customIsotopics.py b/armi/reactor/blueprints/tests/test_customIsotopics.py index f20cec81b..a69576895 100644 --- a/armi/reactor/blueprints/tests/test_customIsotopics.py +++ b/armi/reactor/blueprints/tests/test_customIsotopics.py @@ -309,7 +309,12 @@ class TestCustomIsotopics(unittest.TestCase): @classmethod def setUpClass(cls): cs = settings.Settings() - cs = cs.modified(newSettings={CONF_XS_KERNEL: "MC2v2"}) + cs = cs.modified( + newSettings={ + CONF_XS_KERNEL: "MC2v2", + "inputHeightsConsideredHot": False, + } + ) cls.bp = blueprints.Blueprints.load(cls.yamlString) cls.a = cls.bp.constructAssem(cs, name="fuel a") @@ -356,14 +361,19 @@ def test_densitiesAppliedToNonCustomMaterials(self): # A block with custom density set via number density fuel8 = self.a[8].getComponent(Flags.FUEL) + dLL = fuel2.material.linearExpansionFactor(Tc=600, T0=25) + # the exponent here is 3 because inputHeightsConsideredHot = False. + # if inputHeightsConsideredHot were True, then we would use a factor of 2 instead + f = 1 / ((1 + dLL) ** 3) + # Check that the density is set correctly on the custom density block, # and that it is not the same as the original - self.assertAlmostEqual(19.1, fuel2.density()) + self.assertAlmostEqual(19.1 * f, fuel2.density()) self.assertNotAlmostEqual(fuel0.density(), fuel2.density(), places=2) # Check that the custom density block has the correct material self.assertEqual("UZr", fuel2.material.name) # Check that the block with only number densities set has a new density - self.assertAlmostEqual(19.1, fuel8.density()) + self.assertAlmostEqual(19.1 * f, fuel8.density()) # original material density should not be changed after setting a custom density component, # so a new block without custom isotopics and density should have the same density as the original self.assertAlmostEqual(fuel6.density(), fuel0.density()) From 6a06967bf06e00039a257d4a16d505a135752254 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:34:43 -0600 Subject: [PATCH 09/18] Pass just the boolean inputHeightsConsideredHot down the chain, instead of the whole cs --- armi/reactor/blueprints/blockBlueprint.py | 7 ++++++- armi/reactor/blueprints/componentBlueprint.py | 17 +++++++++-------- .../reactor/blueprints/tests/test_blueprints.py | 3 ++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/armi/reactor/blueprints/blockBlueprint.py b/armi/reactor/blueprints/blockBlueprint.py index 46f148f8d..a1e7a5543 100644 --- a/armi/reactor/blueprints/blockBlueprint.py +++ b/armi/reactor/blueprints/blockBlueprint.py @@ -28,6 +28,7 @@ from armi.reactor.composites import Composite from armi.reactor.converters import blockConverters from armi.reactor.flags import Flags +from armi.settings.fwSettings.globalSettings import CONF_INPUT_HEIGHTS_HOT def _configureGeomOptions(): @@ -144,7 +145,11 @@ def construct( filteredMaterialInput, byComponentMatModKeys = self._filterMaterialInput( materialInput, componentDesign ) - c = componentDesign.construct(cs, blueprint, filteredMaterialInput) + c = componentDesign.construct( + blueprint, + filteredMaterialInput, + cs[CONF_INPUT_HEIGHTS_HOT], + ) components[c.name] = c # check that the mat mods for this component are valid options diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index f1a05aac6..d9bfba943 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -27,7 +27,6 @@ from armi.reactor.flags import Flags from armi.utils import densityTools from armi.nucDirectory import nuclideBases -from armi.settings.fwSettings.globalSettings import CONF_INPUT_HEIGHTS_HOT COMPONENT_GROUP_SHAPE = "group" @@ -187,7 +186,7 @@ def shape(self, shape): mergeWith = yamlize.Attribute(type=str, default=None) area = yamlize.Attribute(type=float, default=None) - def construct(self, cs, blueprint, matMods): + def construct(self, blueprint, matMods, inputHeightsConsideredHot): """Construct a component or group. .. impl:: User-defined on material alterations are applied here. @@ -209,14 +208,14 @@ class can then use to modify the isotopics as necessary. Parameters ---------- - cs : Settings - Settings object for the appropriate simulation. - blueprint : Blueprints Blueprints object containing various detailed information, such as nuclides to model matMods : dict Material modifications to apply to the component. + + inputHeightsConsideredHot : bool + See the case setting of the same name. """ runLog.debug("Constructing component {}".format(self.name)) kwargs = self._conformKwargs(blueprint, matMods) @@ -226,7 +225,9 @@ class can then use to modify the isotopics as necessary. constructedObject = composites.Composite(self.name) for groupedComponent in group: componentDesign = blueprint.componentDesigns[groupedComponent.name] - component = componentDesign.construct(cs, blueprint, matMods=dict()) + component = componentDesign.construct( + blueprint, {}, inputHeightsConsideredHot + ) # override free component multiplicity if it's set based on the group definition component.setDimension("mult", groupedComponent.mult) _setComponentFlags(component, self.flags, blueprint) @@ -245,13 +246,13 @@ class can then use to modify the isotopics as necessary. constructedObject, blueprint, matMods, - blockHeightsConsideredHot=cs[CONF_INPUT_HEIGHTS_HOT], + inputHeightsConsideredHot, ) return constructedObject def _setComponentCustomDensity( - self, comp, blueprint, matMods, blockHeightsConsideredHot + self, comp, blueprint, matMods, inputHeightsConsideredHot ): """Apply a custom density to a material with custom isotopics but not a 'custom material'.""" if self.isotopics is None: diff --git a/armi/reactor/blueprints/tests/test_blueprints.py b/armi/reactor/blueprints/tests/test_blueprints.py index 51e291d4f..7827dd5e1 100644 --- a/armi/reactor/blueprints/tests/test_blueprints.py +++ b/armi/reactor/blueprints/tests/test_blueprints.py @@ -32,6 +32,7 @@ from armi.utils import directoryChangers from armi.utils import textProcessors from armi.reactor.blueprints.gridBlueprint import saveToStream +from armi.settings.fwSettings.globalSettings import CONF_INPUT_HEIGHTS_HOT class TestBlueprints(unittest.TestCase): @@ -612,7 +613,7 @@ def test_topLevelComponentInput(self): # which is required during construction of a component design._resolveNuclides(cs) componentDesign = design.componentDesigns["freefuel"] - topComponent = componentDesign.construct(cs, design, matMods=dict()) + topComponent = componentDesign.construct(design, {}, cs[CONF_INPUT_HEIGHTS_HOT]) self.assertEqual(topComponent.getDimension("od", cold=True), 4.0) self.assertGreater(topComponent.getVolume(), 0.0) self.assertGreater(topComponent.getMass("U235"), 0.0) From befd6a7712703c9d831e7b20ef38e725a0878736 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:35:21 -0600 Subject: [PATCH 10/18] Clean things up --- armi/reactor/blueprints/componentBlueprint.py | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index d9bfba943..562183419 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -259,12 +259,12 @@ def _setComponentCustomDensity( # No custom isotopics specified return - density = blueprint.customIsotopics[self.isotopics].density - if density is None: + densityFromCustomIsotopic = blueprint.customIsotopics[self.isotopics].density + if densityFromCustomIsotopic is None: # Nothing to do return - if density <= 0: + if densityFromCustomIsotopic <= 0: runLog.error( "A zero or negative density was specified in a custom isotopics input. " "This is not permitted, if a 0 density material is needed, use 'Void'. " @@ -293,32 +293,26 @@ def _setComponentCustomDensity( "Cannot apply custom densities to materials without density." ) - # Apply a density scaling to account for the temperature change between the input - # temperature `Tinput` and the hot temperature `Thot`. There may be a better place to - # in the initialization to determine if the block height will be interpreted as hot dimensions - # already. - # - # - Apply additional density scaling when the component is added to a block? - # - Apply here? Not great since this requires a case settings to be applied or some pre-knowledge - # of where the component is going to live? + # Apply a density scaling to account for the temperature change between Tinput + # Thot. There may be a better place in the initialization to determine + # if the block height will be interpreted as hot dimensions, which would + # allow us to not have to pass the case settings down this far dLL = comp.material.linearExpansionFactor( Tc=comp.temperatureInC, T0=comp.inputTemperatureInC ) - if blockHeightsConsideredHot: + if inputHeightsConsideredHot: f = 1.0 / (1 + dLL) ** 2 else: f = 1.0 / (1 + dLL) ** 3 scaledDensity = comp.density() / f - densityRatio = density / scaledDensity + densityRatio = densityFromCustomIsotopic / scaledDensity comp.changeNDensByFactor(densityRatio) - # TODO the density in this print is broken after #1852, see - # https://github.com/terrapower/armi/blob/8b9a693f9bc4030eaa3fbcaa394bb7af74ed10bf/armi/reactor/components/component.py#L1332-L1344 runLog.important( "A custom material density was specified in the custom isotopics for non-custom " f"material {mat}. The component density has been altered to " - f"{scaledDensity} at temperature {comp.temperatureInC} C", + f"{comp.density() * scaledDensity} at temperature {comp.temperatureInC} C", single=True, ) From d59e8ab0bd0031f9005412620a776a18a6fac635 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:40:23 -0600 Subject: [PATCH 11/18] Make it an error when the density for a material is overspecified --- armi/reactor/blueprints/componentBlueprint.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index 562183419..a80de11af 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -278,10 +278,9 @@ def _setComponentCustomDensity( if not isinstance(mat, materials.Custom): # check for some problem cases if "TD_frac" in matMods.keys(): - runLog.warning( - "Both TD_frac and a custom density (custom isotopics) has been specified for " - "material {}. The custom density will override the density calculated using " - "TD_frac.".format(self.material) + runLog.error( + f"Both TD_frac and a custom isotopic with density {blueprint.customIsotopics[self.isotopics]} " + f"has been specified for material {self.material}. This is an overspecification." ) if not mat.density(Tc=self.Tinput) > 0: runLog.error( From c1270dfa990814806167e822cd783357992112e1 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:54:36 -0600 Subject: [PATCH 12/18] Fix runLog statement --- armi/reactor/blueprints/componentBlueprint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armi/reactor/blueprints/componentBlueprint.py b/armi/reactor/blueprints/componentBlueprint.py index a80de11af..289a0de8f 100644 --- a/armi/reactor/blueprints/componentBlueprint.py +++ b/armi/reactor/blueprints/componentBlueprint.py @@ -311,7 +311,7 @@ def _setComponentCustomDensity( runLog.important( "A custom material density was specified in the custom isotopics for non-custom " f"material {mat}. The component density has been altered to " - f"{comp.density() * scaledDensity} at temperature {comp.temperatureInC} C", + f"{comp.density()} at temperature {comp.temperatureInC} C", single=True, ) From 53ff4d343e046bbf18666c599cf558616ed6d78f Mon Sep 17 00:00:00 2001 From: ckeckler Date: Sun, 1 Dec 2024 17:57:18 -0600 Subject: [PATCH 13/18] Fix test that changed due to a different runLog statement --- armi/reactor/blueprints/tests/test_customIsotopics.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/armi/reactor/blueprints/tests/test_customIsotopics.py b/armi/reactor/blueprints/tests/test_customIsotopics.py index a69576895..c132e159d 100644 --- a/armi/reactor/blueprints/tests/test_customIsotopics.py +++ b/armi/reactor/blueprints/tests/test_customIsotopics.py @@ -397,7 +397,11 @@ def test_customDensityLogsAndErrors(self): # Check for log messages streamVal = mockLog.getStdout() - self.assertIn("Both TD_frac and a custom density", streamVal, msg=streamVal) + self.assertIn( + "Both TD_frac and a custom isotopic with density", + streamVal, + msg=streamVal, + ) self.assertIn( "A custom material density was specified", streamVal, msg=streamVal ) From 4fc801242d59a535eff8fdfbceb0d66d7d91c694 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Mon, 2 Dec 2024 16:23:47 -0600 Subject: [PATCH 14/18] Update runLog statement for clarity --- armi/reactor/blueprints/isotopicOptions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/armi/reactor/blueprints/isotopicOptions.py b/armi/reactor/blueprints/isotopicOptions.py index 6bbd3710c..b32a9153d 100644 --- a/armi/reactor/blueprints/isotopicOptions.py +++ b/armi/reactor/blueprints/isotopicOptions.py @@ -396,10 +396,10 @@ def apply(self, material): if not isinstance(material, materials.Custom): # TODO I think this warning should go away? runLog.important( - "A custom density or number densities has been specified for non-custom " - "material {}. The material object's density will not be updated to prevent unintentional " - "density changes across the model. Only custom materials may have a density " - "specified.".format(material), + "A custom isotopic with associated density has been specified for non-`Custom` " + f"material {material}. The reference density of materials in the materials library " + "will not be changed, but the associated components will use the density " + "implied by the custom isotopics.", single=True, ) # specifically, non-Custom materials only use refDensity and dLL, mat.customDensity has no effect From 2cfe89b8c3148896d14846469d0c272c3a6d3ab2 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Mon, 2 Dec 2024 16:24:11 -0600 Subject: [PATCH 15/18] Remove TODO --- armi/reactor/blueprints/isotopicOptions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/armi/reactor/blueprints/isotopicOptions.py b/armi/reactor/blueprints/isotopicOptions.py index b32a9153d..e8b2b3544 100644 --- a/armi/reactor/blueprints/isotopicOptions.py +++ b/armi/reactor/blueprints/isotopicOptions.py @@ -394,7 +394,6 @@ def apply(self, material): material.massFrac = dict(self.massFracs) if self.density is not None: if not isinstance(material, materials.Custom): - # TODO I think this warning should go away? runLog.important( "A custom isotopic with associated density has been specified for non-`Custom` " f"material {material}. The reference density of materials in the materials library " From e483fefee29fa7acca5164de76283fb9e398ab63 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Mon, 2 Dec 2024 16:26:22 -0600 Subject: [PATCH 16/18] Update test for runLog wording change --- armi/reactor/blueprints/tests/test_customIsotopics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armi/reactor/blueprints/tests/test_customIsotopics.py b/armi/reactor/blueprints/tests/test_customIsotopics.py index c132e159d..d971cb658 100644 --- a/armi/reactor/blueprints/tests/test_customIsotopics.py +++ b/armi/reactor/blueprints/tests/test_customIsotopics.py @@ -406,7 +406,7 @@ def test_customDensityLogsAndErrors(self): "A custom material density was specified", streamVal, msg=streamVal ) self.assertIn( - "A custom density or number densities has been specified", + "A custom isotopic with associated density has been specified for non-`Custom`", streamVal, msg=streamVal, ) From 7da315a1c537cb30edf4df6549ad056c8cdde6f4 Mon Sep 17 00:00:00 2001 From: ckeckler Date: Tue, 3 Dec 2024 08:40:22 -0600 Subject: [PATCH 17/18] Add release notes --- doc/release/0.5.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst index 91a786eea..f62fe0ff4 100644 --- a/doc/release/0.5.rst +++ b/doc/release/0.5.rst @@ -97,6 +97,7 @@ Bug Fixes #. Fixed hex block rotation in ``plotBlockDiagram``. (`PR#1926 `_) #. Fixed edge case in ``assemblyBlueprint._checkParamConsistency()``. (`PR#1928 `_) #. Fixed wetted perimeter for hex inner ducts. (`PR#1985 `_) +#. Fixed number densities when custom isotopics and material classes are combined on a component (`PR#1822 `_) Quality Work ------------ From c33c893bcee932d3103757920ec177aef102b4bc Mon Sep 17 00:00:00 2001 From: Chris Keckler Date: Tue, 3 Dec 2024 10:03:16 -0700 Subject: [PATCH 18/18] Update doc/release/0.5.rst Co-authored-by: John Stilley <1831479+john-science@users.noreply.github.com> --- doc/release/0.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst index f62fe0ff4..a589a7963 100644 --- a/doc/release/0.5.rst +++ b/doc/release/0.5.rst @@ -97,7 +97,7 @@ Bug Fixes #. Fixed hex block rotation in ``plotBlockDiagram``. (`PR#1926 `_) #. Fixed edge case in ``assemblyBlueprint._checkParamConsistency()``. (`PR#1928 `_) #. Fixed wetted perimeter for hex inner ducts. (`PR#1985 `_) -#. Fixed number densities when custom isotopics and material classes are combined on a component (`PR#1822 `_) +#. Fixing number densities when custom isotopics and material properties are combined. (`PR#1822 `_) Quality Work ------------