Repository: terrapower/armi

Issue:
Non-grid components have multiplicity of zero
Using the inputs from #251, even if I force the multiplicity to be one with
```yaml
blocks:
    fuel: &block_fuel
        grid name: pins
        duct: &comp_duct
            shape: Hexagon
            material: HT9
            Tinput: 600
            Thot: 600
            ip: 32
            op: 32.2
            mult: 1
```
the duct still has no multiplicity
```python
import armi
from armi.reactor.flags import Flags
armi.configure()
o = armi.init(fName="minicore.yaml")
f = o.r.core.getFirstBlock(Flags.FUEL)
d = f.getComponentByName("duct")
d.getDimension("op")
32.2
d.getDimension("ip")
32.0
d.getDimension("mult")
0
d.getArea()
0.0
```
per https://github.com/terrapower/armi/blob/9e7c2984eae29ad0bb9752f9769cc17a7d12fec0/armi/reactor/components/basicShapes.py#L133-L138

This leads to problems when ARMI is computing volume fractions and can produce divide by zero errors in 
https://github.com/terrapower/armi/blob/9e7c2984eae29ad0bb9752f9769cc17a7d12fec0/armi/reactor/composites.py#L1544

Discussion:

Patch:
diff --git a/armi/reactor/blueprints/blockBlueprint.py b/armi/reactor/blueprints/blockBlueprint.py
index f420d940..049ec2c7 100644
--- a/armi/reactor/blueprints/blockBlueprint.py
+++ b/armi/reactor/blueprints/blockBlueprint.py
@@ -111,19 +111,25 @@ class BlockBlueprint(yamlize.KeyedList):
             c = componentDesign.construct(blueprint, materialInput)
             components[c.name] = c
             if spatialGrid:
-                c.spatialLocator = gridDesign.getMultiLocator(
+                componentLocators = gridDesign.getMultiLocator(
                     spatialGrid, componentDesign.latticeIDs
                 )
-                mult = c.getDimension("mult")
-                if mult and mult != 1.0 and mult != len(c.spatialLocator):
-                    raise ValueError(
-                        f"Conflicting ``mult`` input ({mult}) and number of "
-                        f"lattice positions ({len(c.spatialLocator)}) for {c}. "
-                        "Recommend leaving off ``mult`` input when using grids."
-                    )
-                elif not mult or mult == 1.0:
-                    # learn mult from grid definition
-                    c.setDimension("mult", len(c.spatialLocator))
+                if componentLocators:
+                    # this component is defined in the block grid
+                    # We can infer the multiplicity from the grid.
+                    # Otherwise it's a component that is in a block
+                    # with grids but that's not in the grid itself.
+                    c.spatialLocator = componentLocators
+                    mult = c.getDimension("mult")
+                    if mult and mult != 1.0 and mult != len(c.spatialLocator):
+                        raise ValueError(
+                            f"Conflicting ``mult`` input ({mult}) and number of "
+                            f"lattice positions ({len(c.spatialLocator)}) for {c}. "
+                            "Recommend leaving off ``mult`` input when using grids."
+                        )
+                    elif not mult or mult == 1.0:
+                        # learn mult from grid definition
+                        c.setDimension("mult", len(c.spatialLocator))
 
         for c in components.values():
             c._resolveLinkedDims(components)


Test patch:
diff --git a/armi/reactor/blueprints/tests/test_blockBlueprints.py b/armi/reactor/blueprints/tests/test_blockBlueprints.py
index 91128d53..0655a471 100644
--- a/armi/reactor/blueprints/tests/test_blockBlueprints.py
+++ b/armi/reactor/blueprints/tests/test_blockBlueprints.py
@@ -174,6 +174,14 @@ class TestGriddedBlock(unittest.TestCase):
                 seen = True
         self.assertTrue(seen)
 
+    def test_nonLatticeComponentHasRightMult(self):
+        """Make sure non-grid components in blocks with grids get the right multiplicity"""
+        aDesign = self.blueprints.assemDesigns.bySpecifier["IC"]
+        a = aDesign.construct(self.cs, self.blueprints)
+        fuelBlock = a.getFirstBlock(Flags.FUEL)
+        duct = fuelBlock.getComponent(Flags.DUCT)
+        self.assertEqual(duct.getDimension("mult"), 1.0)
+
     def test_explicitFlags(self):
         a1 = self.blueprints.assemDesigns.bySpecifier["IC"].construct(
             self.cs, self.blueprints