Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into uniformMeshFix
Browse files Browse the repository at this point in the history
  • Loading branch information
jakehader committed Aug 11, 2022
2 parents 291118d + c7a453f commit e420916
Show file tree
Hide file tree
Showing 40 changed files with 1,457 additions and 773 deletions.
21 changes: 6 additions & 15 deletions armi/apps.py
Expand Up @@ -31,7 +31,6 @@
from typing import Dict, Optional, Tuple, List
import collections
import importlib
import os
import sys

from armi import context, plugins, pluginManager, meta, settings
Expand Down Expand Up @@ -263,7 +262,7 @@ def registerUserPlugins(self, pluginPaths):
self.__initNewPlugins()

for pluginPath in pluginPaths:
if os.sep in pluginPath:
if ".py:" in pluginPath:
# The path is of the form: /path/to/why.py:MyPlugin
self.__registerUserPluginsAbsPath(pluginPath)
else:
Expand All @@ -274,19 +273,11 @@ def __registerUserPluginsAbsPath(self, pluginPath):
"""Helper method to register a single UserPlugin where
the given path is of the form: /path/to/why.py:MyPlugin
"""
# determine if this is a Windows system
isWindows = False
if os.name == "nt":
isWindows = True

# handle the minor variations on Windows file pathing
if isWindows:
assert pluginPath.count(":") == 2, f"Invalid plugin path: {pluginPath}"
drive, filePath, className = pluginPath.split(":")
filePath = drive + ":" + filePath
else:
assert pluginPath.count(":") == 1, f"Invalid plugin path: {pluginPath}"
filePath, className = pluginPath.split(":")
assert pluginPath.count(".py:") == 1, f"Invalid plugin path: {pluginPath}"

# split the settings string into file path and class name
filePath, className = pluginPath.split(".py:")
filePath += ".py"

spec = importlib.util.spec_from_file_location(className, filePath)
mod = importlib.util.module_from_spec(spec)
Expand Down
12 changes: 10 additions & 2 deletions armi/bookkeeping/db/compareDB3.py
Expand Up @@ -47,6 +47,7 @@
import collections
import os
import re
import traceback

from tabulate import tabulate
import h5py
Expand Down Expand Up @@ -360,8 +361,15 @@ def _diffSpecialData(
if not attrsMatch:
return

src = database3.unpackSpecialData(srcData[()], srcData.attrs, paramName)
ref = database3.unpackSpecialData(refData[()], refData.attrs, paramName)
try:
src = database3.unpackSpecialData(srcData[()], srcData.attrs, paramName)
ref = database3.unpackSpecialData(refData[()], refData.attrs, paramName)
except Exception:
runLog.error(
f"Unable to unpack special data for paramName {paramName}. "
f"{traceback.format_exc()}",
)
return

diff = []
for dSrc, dRef in zip(src.tolist(), ref.tolist()):
Expand Down
5 changes: 2 additions & 3 deletions armi/bookkeeping/db/database3.py
Expand Up @@ -1227,7 +1227,7 @@ def _compose(self, comps, cs, parent=None):
# We only have a good geom for the main core, so can't do process loading on
# the SFP, etc.
if comp.hasFlags(Flags.CORE):
comp.processLoading(cs)
comp.processLoading(cs, dbLoad=True)
elif isinstance(comp, Assembly):
comp.calculateZCoords()

Expand Down Expand Up @@ -1307,8 +1307,7 @@ def _writeParams(self, h5group, comps):
# flatten, store the data offsets and array shapes, and None locations
# as attrs
# - If not jagged, all top-level ndarrays are the same shape, so it is
# probably easier to replace Nones with ndarrays filled with special
# values.
# easier to replace Nones with ndarrays filled with special values.
if parameters.NoDefault in data:
data = None
else:
Expand Down
15 changes: 15 additions & 0 deletions armi/bookkeeping/db/tests/test_comparedb3.py
Expand Up @@ -204,6 +204,21 @@ def test_diffSpecialData(self):
self.assertEqual(dr.nDiffs(), 0)
self.assertIn("Special formatting parameters for", mock._outputStream)

# make an H5 datasets that will cause unpackSpecialData to fail
f4 = h5py.File("test_diffSpecialData4.hdf5", "w")
refData4 = f4.create_dataset("numberDensities", data=a2)
refData4.attrs["shapes"] = "2"
refData4.attrs["numDens"] = a2
f5 = h5py.File("test_diffSpecialData5.hdf5", "w")
srcData5 = f5.create_dataset("numberDensities", data=a2)
srcData5.attrs["shapes"] = "2"
srcData5.attrs["numDens"] = a2

# there should an exception
with self.assertRaises(Exception) as e:
_diffSpecialData(refData4, srcData5, out, dr)
self.assertIn("Unable to unpack special data for paramName", e)

def test_diffSimpleData(self):
dr = DiffResults(0.01)

Expand Down
43 changes: 42 additions & 1 deletion armi/bookkeeping/db/tests/test_database3.py
Expand Up @@ -14,14 +14,16 @@

r""" Tests for the Database3 class
"""
# pylint: disable=missing-function-docstring,missing-class-docstring,abstract-method,protected-access,no-member,disallowed-name,invalid-name
import subprocess
import unittest

import h5py
import numpy

from armi.bookkeeping.db import database3
from armi.bookkeeping.db import _getH5File, database3
from armi.reactor import grids
from armi.reactor import parameters
from armi.reactor.tests import test_reactors
from armi.tests import TEST_ROOT
from armi.utils import getPreviousTimeNode
Expand Down Expand Up @@ -50,6 +52,45 @@ def tearDown(self):
self.stateRetainer.__exit__()
self.td.__exit__(None, None, None)

def test_writeToDB(self):
self.r.p.cycle = 0
self.r.p.timeNode = 0
self.r.p.cycleLength = 0

# Adding some nonsense in, to test NoDefault params
self.r.p.availabilityFactor = parameters.NoDefault

# validate that the H5 file gets bigger after the write
self.assertEqual(list(self.db.h5db.keys()), ["inputs"])
self.db.writeToDB(self.r)
self.assertEqual(sorted(self.db.h5db.keys()), ["c00n00", "inputs"])

keys = [
"Circle",
"Core",
"DerivedShape",
"Helix",
"HexAssembly",
"HexBlock",
"Hexagon",
"Reactor",
"layout",
]
self.assertEqual(sorted(self.db.h5db["c00n00"].keys()), sorted(keys))

# validate availabilityFactor did not make it into the H5 file
rKeys = ["cycle", "cycleLength", "flags", "serialNum", "timeNode"]
self.assertEqual(
sorted(self.db.h5db["c00n00"]["Reactor"].keys()), sorted(rKeys)
)

def test_getH5File(self):
with self.assertRaises(TypeError):
_getH5File(None)

h5 = _getH5File(self.db)
self.assertEqual(type(h5), h5py.File)

def makeHistory(self):
"""Walk the reactor through a few time steps and write them to the db."""
for cycle, node in ((cycle, node) for cycle in range(3) for node in range(3)):
Expand Down
6 changes: 5 additions & 1 deletion armi/bookkeeping/historyTracker.py
Expand Up @@ -295,7 +295,11 @@ def writeAssemHistory(self, a, fName=""):

params = self.getTrackedParams()
blocks = [
b for bi, b in enumerate(a) if bi not in self.cs["stationaryBlocks"]
b
for b in a
if not any(
b.hasFlags(sbf) for sbf in self.r.core.stationaryBlockFlagsList
)
]
blockHistories = dbi.getHistories(blocks, params)

Expand Down
38 changes: 9 additions & 29 deletions armi/bookkeeping/tests/test_historyTracker.py
Expand Up @@ -19,12 +19,12 @@
a valid HDF5 file to load from as a test fixtures. Thus they take a little longer
than usual.
"""
# pylint: disable=missing-function-docstring,missing-class-docstring,protected-access
import os
import pathlib
import shutil
import unittest

from armi import init as armi_init
from armi import settings
from armi import utils
from armi.bookkeeping import historyTracker
Expand All @@ -35,14 +35,15 @@
from armi.reactor import grids
from armi.reactor.flags import Flags
from armi.tests import ArmiTestHelper
from armi.utils import directoryChangers
from armi.utils.directoryChangers import TemporaryDirectoryChanger

CASE_TITLE = "anl-afci-177"
THIS_DIR = os.path.dirname(__file__) # b/c tests don't run in this folder
TUTORIAL_DIR = os.path.join(ROOT, "tests", "tutorials")


def runTutorialNotebook():
# pylint: disable=import-outside-toplevel
import nbformat
from nbconvert.preprocessors import ExecutePreprocessor

Expand All @@ -57,35 +58,14 @@ class TestHistoryTracker(ArmiTestHelper):

@classmethod
def setUpClass(cls):
# Not using a directory changer since it isn't important that we go back in the
# first place, and we don't want to get tangled with the directory change below.
# We need to be in the TUTORIAL_DIR in the first place so that for `filesToMove`
# to work right.
# We need to be in the TUTORIAL_DIR so that for `filesToMove` to work right.
os.chdir(TUTORIAL_DIR)

# Make sure to do this work in a temporary directory to avoid race conditions
# when running tests in parallel with xdist.
cls.dirChanger = directoryChangers.TemporaryDirectoryChanger(
filesToMove=TUTORIAL_FILES
)
# Do this work in a temp dir, to avoid race conditions.
cls.dirChanger = TemporaryDirectoryChanger(filesToMove=TUTORIAL_FILES)
cls.dirChanger.__enter__()
runTutorialNotebook()

reloadCs = settings.Settings(f"{CASE_TITLE}.yaml")

newSettings = {}
newSettings["db"] = True
newSettings["reloadDBName"] = pathlib.Path(f"{CASE_TITLE}.h5").absolute()
newSettings["runType"] = "Snapshots"
newSettings["loadStyle"] = "fromDB"
newSettings["detailAssemLocationsBOL"] = ["001-001"]

reloadCs = reloadCs.modified(newSettings=newSettings)
reloadCs.caseTitle = "armiRun"

o = armi_init(cs=reloadCs)
cls.o = o

@classmethod
def tearDownClass(cls):
cls.dirChanger.__exit__(None, None, None)
Expand All @@ -94,13 +74,13 @@ def setUp(self):
cs = settings.Settings(f"{CASE_TITLE}.yaml")
newSettings = {}
newSettings["db"] = True
newSettings["reloadDBName"] = pathlib.Path(f"{CASE_TITLE}.h5").absolute()
newSettings["loadStyle"] = "fromDB"
newSettings["detailAssemLocationsBOL"] = ["001-001"]
newSettings["loadStyle"] = "fromDB"
newSettings["reloadDBName"] = pathlib.Path(f"{CASE_TITLE}.h5").absolute()
newSettings["startNode"] = 1
cs = cs.modified(newSettings=newSettings)

self.td = directoryChangers.TemporaryDirectoryChanger()
self.td = TemporaryDirectoryChanger()
self.td.__enter__()

c = case.Case(cs)
Expand Down

0 comments on commit e420916

Please sign in to comment.