Skip to content

Commit

Permalink
Merge 80596e2 into 09c26c7
Browse files Browse the repository at this point in the history
  • Loading branch information
youngmit committed Aug 19, 2021
2 parents 09c26c7 + 80596e2 commit 1e6d3c2
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 41 deletions.
21 changes: 20 additions & 1 deletion armi/mpiActions.py
Expand Up @@ -68,6 +68,7 @@
from armi import interfaces
from armi.reactor import reactors
from armi.reactor import assemblies
from armi.reactor.parameters import parameterDefinitions
from armi import utils
from armi.utils import iterables

Expand Down Expand Up @@ -469,6 +470,7 @@ def invokeHook(self):
cs = self._distributeSettings()

self._distributeReactor(cs)
self._distributeParamAssignments()

if self._skipInterfaces:
self.o.reattach(self.r, cs) # may be redundant?
Expand All @@ -481,7 +483,7 @@ def invokeHook(self):
# same.
# XXX: this is an indication we need to revamp either how the operator attachment works
# or how the interfaces are distributed.
self.r.core._markSynchronized() # pylint: disable=protected-access
self.r._markSynchronized() # pylint: disable=protected-access

except (cPickle.PicklingError, TypeError) as error:
runLog.error("Failed to transmit on distribute state root MPI bcast")
Expand Down Expand Up @@ -557,6 +559,23 @@ def _distributeReactor(self, cs):
# attach here so any interface actions use a properly-setup reactor.
self.o.reattach(self.r, cs) # sets r and cs

def _distributeParamAssignments(self):
data = dict()
if armi.MPI_RANK == 0:
data = {
(pName, pdType.__name__): pDef.assigned
for (
pName,
pdType,
), pDef in parameterDefinitions.ALL_DEFINITIONS.items()
}

data = armi.MPI_COMM.bcast(data, root=0)

if armi.MPI_RANK != 0:
for (pName, pdType), pDef in parameterDefinitions.ALL_DEFINITIONS.items():
pDef.assigned = data[pName, pdType.__name__]

def _distributeInterfaces(self):
"""
Distribute the interfaces to all MPI nodes.
Expand Down
2 changes: 1 addition & 1 deletion armi/reactor/composites.py
Expand Up @@ -2854,7 +2854,7 @@ def syncMpiState(self):
number of parameters synchronized over all components
"""
if armi.MPI_SIZE == 1:
return
return 0

startTime = timeit.default_timer()
# sync parameters...
Expand Down
3 changes: 3 additions & 0 deletions armi/reactor/parameters/parameterDefinitions.py
Expand Up @@ -429,6 +429,9 @@ def _filter(self, filterFunc):
pdc.extend(filter(filterFunc, self._paramDefs))
return pdc

def items(self):
return self._paramDefDict.items()

def extend(self, other):
"""
Grow a parameter definition collection by another parameter definition collection
Expand Down
58 changes: 19 additions & 39 deletions armi/tests/test_mpiActions.py
Expand Up @@ -22,6 +22,9 @@
from armi import settings
from armi import nuclearDataIO
from armi import mpiActions
from armi.reactor import reactors
from armi.reactor import blueprints
from armi.reactor.parameters import parameterDefinitions
from armi.utils import iterables
from armi.operators import OperatorMPI
from armi.nucDirectory import nuclideBases
Expand Down Expand Up @@ -81,8 +84,11 @@ def invokeHook(self):
class MpiDistributeStateTests(unittest.TestCase):
def setUp(self):
self.cs = settings.Settings(fName=ARMI_RUN_PATH)
bp = blueprints.loadFromCs(self.cs)

settings.setMasterCs(self.cs)
self.o = OperatorMPI(self.cs)
self.o.r = reactors.factory(self.cs, bp)
self.action = DistributeStateAction()
self.action.o = self.o
self.action.r = self.o.r
Expand All @@ -101,55 +107,28 @@ def test_distributeSettings(self):
ss.name: ss.value for ss in self.action.o.cs.settings.values()
}
# remove values that are *expected to be* different...
for key in ["stationaryBlocks", "verbosity"]:
# self.assertNotEqual(original.get(key, None),
# current.get(key, None))
# crossSectionControl is removed because unittest is being mean about
# comparing dicts...
for key in ["stationaryBlocks", "verbosity", "crossSectionControl"]:
if key in original:
del original[key]
if key in current:
del current[key]
# for key in set(original.keys() + current.keys()):
# self.assertEqual(original[key],
# current[key],
# 'Values for key `{}\' are different {} != {}'
# .format(key, original[key], current[key]))
self.assertEqual(original, current)
for key, val in original.items():
self.assertEqual(original[key], current[key])

def test_distributeReactor(self):
"""Under normal circumstances, we would not test "private" methods;
however, distributeState is quite complicated.
"""
original_reactor = self.action.r
self.action._distributeReactor(self.cs)
self.assertIsNone(self.action.o.r.o)
if armi.MPI_RANK == 0:
self.assertEqual(original_reactor, self.action.r)
else:
self.assertNotEqual(original_reactor, self.action.r)
self.assertIsNone(self.action.r.core.lib)

def test_distributeReactorWithIsotxs(self):
"""Under normal circumstances, we would not test "private" methods;
however, distributeState is quite complicated.
"""
original_reactor = self.action.r
self.assertIsNone(self.action.r.core.lib)
if armi.MPI_RANK == 0:
original_reactor.lib = nuclearDataIO.isotxs.readBinary(ISOAA_PATH)
self.action._distributeReactor(self.cs)
actual = {nb.label: nb.mc2id for nb in self.o.r.core.lib.nuclides}
if armi.MPI_RANK == 0:
self.assertEqual(original_reactor.lib, self.action.r.core.lib)
armi.MPI_COMM.bcast(actual) # soon to become expected
else:
self.assertIsNotNone(self.action.r.core.lib)
for nuclide in self.action.r.core.lib.nuclides:
self.assertEqual(
nuclideBases.byLabel[nuclide._base.label], nuclide._base
)
expected = armi.MPI_COMM.bcast(None)
self.assertEqual(expected, actual)

def test_distributeInterfaces(self):
"""Under normal circumstances, we would not test "private" methods;
however, distributeState is quite complicated.
Expand All @@ -165,26 +144,27 @@ def test_distributeState(self):
original_reactor = self.o.r
original_lib = self.o.r.core.lib
original_interfaces = self.o.interfaces
original_bolassems = self.o.r.blueprints.assemblies.values()
original_bolassems = self.o.r.blueprints.assemblies
self.action.invokeHook()

if armi.MPI_RANK == 0:
self.assertEqual(self.cs, self.o.cs)
self.assertEqual(original_reactor, self.o.r)
self.assertEqual(original_interfaces, self.o.interfaces)
self.assertEqual(
original_bolassems, self.o.r.blueprints.assemblies.values()
)
self.assertDictEqual(original_bolassems, self.o.r.blueprints.assemblies)
self.assertEqual(original_lib, self.o.r.core.lib)
else:
self.assertNotEqual(self.cs, self.o.cs)
self.assertNotEqual(original_reactor, self.o.r)
self.assertNotEqual(
original_bolassems, self.o.r.blueprints.assemblies.values()
)
self.assertNotEqual(original_bolassems, self.o.r.blueprints.assemblies)
self.assertEqual(original_interfaces, self.o.interfaces)
self.assertEqual(original_lib, self.o.r.core.lib)

for pDef in parameterDefinitions.ALL_DEFINITIONS:
self.assertFalse(
pDef.assigned & parameterDefinitions.SINCE_LAST_DISTRIBUTE_STATE
)

def test_compileResults(self):

action1 = BcastAction1()
Expand Down

0 comments on commit 1e6d3c2

Please sign in to comment.