From e889ca9b49d066175ccc461333dbfe11c632ca95 Mon Sep 17 00:00:00 2001 From: aalberti Date: Mon, 23 Jan 2023 11:23:45 -0800 Subject: [PATCH 1/5] expose tight coupling to OperatorSnapshots --- armi/operators/operator.py | 5 ++++- armi/operators/snapshots.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/armi/operators/operator.py b/armi/operators/operator.py index bfa26be7f..b316ddde5 100644 --- a/armi/operators/operator.py +++ b/armi/operators/operator.py @@ -378,7 +378,10 @@ def _timeNodeLoop(self, cycle, timeNode): """Run the portion of the main loop that happens each subcycle.""" self.r.p.timeNode = timeNode self.interactAllEveryNode(cycle, timeNode) - # perform tight coupling if requested + self._performTightCoupling(cycle, timeNode) + + def _performTightCoupling(self, cycle: int, timeNode: int): + """if requested, perform tight coupling""" if self.couplingIsActive(): self._convergenceSummary = collections.defaultdict(list) for coupledIteration in range(self.cs["tightCouplingMaxNumIters"]): diff --git a/armi/operators/snapshots.py b/armi/operators/snapshots.py index 742254fce..bca8ec5c7 100644 --- a/armi/operators/snapshots.py +++ b/armi/operators/snapshots.py @@ -76,6 +76,7 @@ def _mainOperate(self): self.interactAllEveryNode( ssCycle, ssNode, excludedInterfaceNames=("database",) ) + self._performTightCoupling(ssCycle, ssNode) # database is excluded at last snapshot since it writes at EOL exclude = ("database",) if (ssCycle, ssNode) == lastTimeStep else () From eade9a4d65bd96afe020185746b0ee6a20d6c140 Mon Sep 17 00:00:00 2001 From: aalberti Date: Mon, 23 Jan 2023 11:29:17 -0800 Subject: [PATCH 2/5] release notes --- doc/release/0.2.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release/0.2.rst b/doc/release/0.2.rst index 7b99666bd..97a55a502 100644 --- a/doc/release/0.2.rst +++ b/doc/release/0.2.rst @@ -27,6 +27,7 @@ What's new in ARMI #. Allow MCNP material card number to be defined after the card is written. (`PR#1086 `_) #. Refine logic for Block.getNumPins() to only count components that are actually pins. (`PR#1098 `_) #. Improve handling of peak/max parameters by the UniformMeshConverter parameter mapper. (`PR#1108 `_) +#. Bug fix to expose new tight coupling functionality to ``OperatorSnapshots``. (`PR#1113 https://github.com/terrapower/armi/pull/1113`_) Bug fixes --------- From 5a6001582f26bb72d54a92971d11d9e12d01e28c Mon Sep 17 00:00:00 2001 From: aalberti Date: Mon, 23 Jan 2023 14:51:45 -0800 Subject: [PATCH 3/5] bug fix for writing out DB for OperatorSnapshot --- armi/operators/operator.py | 16 +++++++++++----- armi/operators/snapshots.py | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/armi/operators/operator.py b/armi/operators/operator.py index b316ddde5..12490e220 100644 --- a/armi/operators/operator.py +++ b/armi/operators/operator.py @@ -380,8 +380,13 @@ def _timeNodeLoop(self, cycle, timeNode): self.interactAllEveryNode(cycle, timeNode) self._performTightCoupling(cycle, timeNode) - def _performTightCoupling(self, cycle: int, timeNode: int): - """if requested, perform tight coupling""" + def _performTightCoupling(self, cycle: int, timeNode: int, writeDB: bool = True): + """if requested, perform tight coupling and write out database + + Notes + ----- + writeDB is False for OperatorSnapshots as the DB gets written at EOL. + """ if self.couplingIsActive(): self._convergenceSummary = collections.defaultdict(list) for coupledIteration in range(self.cs["tightCouplingMaxNumIters"]): @@ -389,9 +394,10 @@ def _performTightCoupling(self, cycle: int, timeNode: int): converged = self.interactAllCoupled(coupledIteration) if converged: break - # database has not yet been written, so we need to write it. - dbi = self.getInterface("database") - dbi.writeDBEveryNode(cycle, timeNode) + if writeDB: + # database has not yet been written, so we need to write it. + dbi = self.getInterface("database") + dbi.writeDBEveryNode(cycle, timeNode) def _interactAll(self, interactionName, activeInterfaces, *args): """ diff --git a/armi/operators/snapshots.py b/armi/operators/snapshots.py index bca8ec5c7..34e8dc207 100644 --- a/armi/operators/snapshots.py +++ b/armi/operators/snapshots.py @@ -76,7 +76,7 @@ def _mainOperate(self): self.interactAllEveryNode( ssCycle, ssNode, excludedInterfaceNames=("database",) ) - self._performTightCoupling(ssCycle, ssNode) + self._performTightCoupling(ssCycle, ssNode, writeDB=False) # database is excluded at last snapshot since it writes at EOL exclude = ("database",) if (ssCycle, ssNode) == lastTimeStep else () From 1b2ddbb521148c938db36cf32be949aaafc8e800 Mon Sep 17 00:00:00 2001 From: aalberti Date: Tue, 24 Jan 2023 08:43:50 -0800 Subject: [PATCH 4/5] initial crack at tests --- armi/operators/tests/test_operators.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/armi/operators/tests/test_operators.py b/armi/operators/tests/test_operators.py index 23a371b04..4a498949e 100644 --- a/armi/operators/tests/test_operators.py +++ b/armi/operators/tests/test_operators.py @@ -27,6 +27,8 @@ from armi.physics.neutronics.globalFlux.globalFluxInterface import ( GlobalFluxInterfaceUsingExecuters, ) +from armi.utils import directoryChangers +from armi.bookkeeping.db.databaseInterface import DatabaseInterface class InterfaceA(Interface): @@ -107,6 +109,30 @@ def test_couplingIsActive(self): self.o.cs["tightCoupling"] = True self.assertTrue(self.o.couplingIsActive()) + def test_dbWrittenForCoupling(self): + with directoryChangers.TemporaryDirectoryChanger(): + self.o.cs["tightCoupling"] = True + self.o.removeAllInterfaces() + dbi = DatabaseInterface(self.r, self.o.cs) + dbi.initDB(fName=self._testMethodName + ".h5") + self.o.addInterface(dbi) + self.o._performTightCoupling(0, 0, writeDB=True) + h5Contents = list(dbi.database.getH5Group(dbi.r).items()) + self.assertTrue(h5Contents) + dbi.database.close() + + def test_dbNotWrittenForCoupling(self): + with directoryChangers.TemporaryDirectoryChanger(): + self.o.cs["tightCoupling"] = True + self.o.removeAllInterfaces() + dbi = DatabaseInterface(self.r, self.o.cs) + dbi.initDB(fName=self._testMethodName + ".h5") + self.o.addInterface(dbi) + self.o._performTightCoupling(0, 0, writeDB=False) + h5Contents = list(dbi.database.getH5Group(dbi.r).items()) + self.assertFalse(h5Contents) + dbi.database.close() + def test_computeTightCouplingConvergence(self): """ensure that tight coupling convergence can be computed and checked From 86f406024bb04aa9d8c1b90fb4ee34938655f191 Mon Sep 17 00:00:00 2001 From: aalberti Date: Tue, 24 Jan 2023 08:47:38 -0800 Subject: [PATCH 5/5] refactor tests --- armi/operators/tests/test_operators.py | 33 +++++++++++--------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/armi/operators/tests/test_operators.py b/armi/operators/tests/test_operators.py index 4a498949e..0df30782e 100644 --- a/armi/operators/tests/test_operators.py +++ b/armi/operators/tests/test_operators.py @@ -109,29 +109,24 @@ def test_couplingIsActive(self): self.o.cs["tightCoupling"] = True self.assertTrue(self.o.couplingIsActive()) - def test_dbWrittenForCoupling(self): + def test_dbWriteForCoupling(self): with directoryChangers.TemporaryDirectoryChanger(): self.o.cs["tightCoupling"] = True - self.o.removeAllInterfaces() - dbi = DatabaseInterface(self.r, self.o.cs) - dbi.initDB(fName=self._testMethodName + ".h5") - self.o.addInterface(dbi) - self.o._performTightCoupling(0, 0, writeDB=True) - h5Contents = list(dbi.database.getH5Group(dbi.r).items()) + self.dbWriteForCoupling(writeDB=True) + self.dbWriteForCoupling(writeDB=False) + + def dbWriteForCoupling(self, writeDB: bool): + self.o.removeAllInterfaces() + dbi = DatabaseInterface(self.r, self.o.cs) + dbi.initDB(fName=self._testMethodName + ".h5") + self.o.addInterface(dbi) + self.o._performTightCoupling(0, 0, writeDB=writeDB) + h5Contents = list(dbi.database.getH5Group(dbi.r).items()) + if writeDB: self.assertTrue(h5Contents) - dbi.database.close() - - def test_dbNotWrittenForCoupling(self): - with directoryChangers.TemporaryDirectoryChanger(): - self.o.cs["tightCoupling"] = True - self.o.removeAllInterfaces() - dbi = DatabaseInterface(self.r, self.o.cs) - dbi.initDB(fName=self._testMethodName + ".h5") - self.o.addInterface(dbi) - self.o._performTightCoupling(0, 0, writeDB=False) - h5Contents = list(dbi.database.getH5Group(dbi.r).items()) + else: self.assertFalse(h5Contents) - dbi.database.close() + dbi.database.close() def test_computeTightCouplingConvergence(self): """ensure that tight coupling convergence can be computed and checked