Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/terrapower/armi into entryp…
Browse files Browse the repository at this point in the history
…oint
  • Loading branch information
opotowsky committed Oct 6, 2022
2 parents 249a736 + b4e477c commit 5dbf670
Show file tree
Hide file tree
Showing 16 changed files with 176 additions and 71 deletions.
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ omit =
armi/utils/tests/test_gridGui.py
venv/
source = armi
# change default .coverage file to something that doesn't have a dot
# because our Windows file server can't handle dots. :s
data_file = coverage_results.cov

[coverage:run]
parallel = true
Expand Down
31 changes: 28 additions & 3 deletions armi/cases/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
import glob
import os
import pathlib
import platform
import pstats
import re
import shutil
import sys
import textwrap
import time
Expand Down Expand Up @@ -380,7 +382,7 @@ def _startCoverage(self):
cov = None
if self.cs["coverage"]:
cov = coverage.Coverage(
config_file=os.path.join(context.RES, "coveragerc"), debug=["dataio"]
config_file=Case._getCoverageRcFile(makeCopy=True), debug=["dataio"]
)
if context.MPI_SIZE > 1:
# interestingly, you cannot set the parallel flag in the constructor
Expand Down Expand Up @@ -415,8 +417,7 @@ def _endCoverage(cov=None):
# combine all the parallel coverage data files into one and make
# the XML and HTML reports for the whole run.
combinedCoverage = coverage.Coverage(
config_file=os.path.join(context.RES, "coveragerc"),
debug=["dataio"],
config_file=Case._getCoverageRcFile(), debug=["dataio"]
)
combinedCoverage.config.parallel = True
# combine does delete the files it merges
Expand All @@ -425,6 +426,30 @@ def _endCoverage(cov=None):
combinedCoverage.html_report()
combinedCoverage.xml_report()

@staticmethod
def _getCoverageRcFile(makeCopy=False):
"""Helper to provide the coverage configuration file according to the OS.
Parameters
----------
makeCopy : bool (optional)
Whether or not to copy the coverage config file to an alternate file path
Returns
-------
covFile : str
path of coveragerc file
"""
covRcDir = os.path.abspath(context.PROJECT_ROOT)
covFile = os.path.join(covRcDir, ".coveragerc")
if platform.system() == "Windows":
covFileWin = os.path.join(covRcDir, "coveragerc")
if makeCopy == True:
# Make a copy of the file without the dot in the name
shutil.copy(covFile, covFileWin)
return covFileWin
return covFile

def _startProfiling(self):
"""Helper to the Case.run(): start the Python profiling,
if the CaseSettings file says to.
Expand Down
13 changes: 10 additions & 3 deletions armi/cases/tests/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@
import logging
import os
import platform
import sys
import unittest

import coverage

from armi import cases
from armi import context
from armi import getApp
Expand Down Expand Up @@ -124,6 +121,16 @@ def test_independentVariables(self):
for name, val in vals.items():
self.assertEqual(newCase.independentVariables[name], val)

def test_getCoverageRcFile(self):
case = cases.Case(settings.Settings())
covRcDir = os.path.abspath(context.PROJECT_ROOT)
# Don't actually copy the file, just check the file paths match
covRcFile = case._getCoverageRcFile(makeCopy=False)
if platform.system() == "Windows":
self.assertEqual(covRcFile, os.path.join(covRcDir, "coveragerc"))
else:
self.assertEqual(covRcFile, os.path.join(covRcDir, ".coveragerc"))

def test_startCoverage(self):
with directoryChangers.TemporaryDirectoryChanger():
cs = settings.Settings(ARMI_RUN_PATH)
Expand Down
9 changes: 8 additions & 1 deletion armi/cli/modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ def addOptions(self):
default=".",
help="A root directory in which to search for settings files, e.g., armi/tests.",
)
self.parser.add_argument(
"--settingsWriteStyle",
type=str,
default="short",
help="Writing style for which settings get written back to the settings files.",
choices=["short", "medium", "full"],
)
self.parser.add_argument(
"patterns",
type=str,
Expand Down Expand Up @@ -102,7 +109,7 @@ def invoke(self):
inspector.run()

if not self.args.list_setting_files:
cs.writeToYamlFile(cs.path)
cs.writeToYamlFile(cs.path, style=self.args.settingsWriteStyle)

runLog.important(
"Finished {} {} settings files.".format(messages[1], len(csInstances))
Expand Down
7 changes: 6 additions & 1 deletion armi/cli/tests/test_runEntryPoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def test_cloneArmiRunCommandBatchBasics(self):

self.assertEqual(ca.name, "clone-batch")
self.assertEqual(ca.settingsArgument, "required")
self.assertEqual(ca.args.additional_files, ["test"])


class TestCloneSuiteCommand(unittest.TestCase):
Expand All @@ -109,6 +110,7 @@ def test_cloneSuiteCommandBasics(self):
cs.parse_args(["-d", "test"])

self.assertEqual(cs.name, "clone-suite")
self.assertEqual(cs.args.directory, "test")


class TestCompareCases(unittest.TestCase):
Expand Down Expand Up @@ -213,10 +215,13 @@ class TestModifyCaseSettingsCommand(unittest.TestCase):
def test_modifyCaseSettingsCommandBasics(self):
mcs = ModifyCaseSettingsCommand()
mcs.addOptions()
mcs.parse_args(["--rootDir", "/path/to/", "fake.yaml"])
mcs.parse_args(
["--rootDir", "/path/to/", "--settingsWriteStyle", "medium", "fake.yaml"]
)

self.assertEqual(mcs.name, "modify")
self.assertEqual(mcs.args.rootDir, "/path/to/")
self.assertEqual(mcs.args.settingsWriteStyle, "medium")
self.assertEqual(mcs.args.patterns, ["fake.yaml"])

def test_modifyCaseSettingsCommandInvoke(self):
Expand Down
3 changes: 2 additions & 1 deletion armi/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ def setMode(cls, mode):


ROOT = os.path.abspath(os.path.dirname(__file__))
PROJECT_ROOT = os.path.join(ROOT, "..")
RES = os.path.join(ROOT, "resources")
DOC = os.path.abspath(os.path.join(ROOT, "..", "doc"))
DOC = os.path.abspath(os.path.join(PROJECT_ROOT, "doc"))
USER = getpass.getuser()
START_TIME = time.ctime()

Expand Down
2 changes: 0 additions & 2 deletions armi/nuclearDataIO/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ def _getNeutronKeywords(cycle, suffix, xsID):
keywords = [xsID]
if suffix not in [None, ""]:
keywords.append("-" + suffix)
else:
raise ValueError("The cycle or XS ID must be specified.")
return keywords


Expand Down
19 changes: 0 additions & 19 deletions armi/operators/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,25 +904,6 @@ def _attachInterfaces(self):
for i in self.interfaces:
i.attachReactor(self, self.r)

def dumpRestartData(self, cycle, time_, factorList):
"""
Write some information about the cycle and shuffling to a auxiliary file for potential restarting.
Notes
-----
This is old and can be deprecated now that the database contains
the entire state. This was historically needed to have complete information regarding
shuffling when figuring out ideal fuel management operations.
"""
if cycle >= len(self.restartData):
self.restartData.append((cycle, time_, factorList))
else:
# try to preserve loaded restartdata so we don't lose it in restarts.
self.restartData[cycle] = (cycle, time_, factorList)
with open(self.cs.caseTitle + ".restart.dat", "w") as restart:
for info in self.restartData:
restart.write("cycle=%d time=%10.6E factorList=%s\n" % info)

def _loadRestartData(self):
"""
Read a restart.dat file which contains all the fuel management factorLists and cycle lengths.
Expand Down
1 change: 1 addition & 0 deletions armi/physics/neutronics/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,7 @@ def linPowByPinGamma(self, value):
units="1/cm^2/s",
description="Neutron flux above 100keV",
location=ParamLocation.AVERAGE,
categories=["detailedAxialExpansion"],
)

pb.defParam(
Expand Down
4 changes: 3 additions & 1 deletion armi/reactor/converters/tests/test_uniformMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ def test_applyStateToOriginal(self):
for b in self.converter.convReactor.core.getBlocks():
b.p.mgFlux = range(33)
b.p.adjMgFlux = range(33)
b.p.flux = 5
b.p.fastFlux = 2.0
b.p.flux = 5.0
b.p.power = 5.0
b.p.pdens = 0.5

Expand All @@ -292,6 +293,7 @@ def test_applyStateToOriginal(self):
self.converter.applyStateToOriginal()

for b in self.r.core.getBlocks():
self.assertAlmostEqual(b.p.fastFlux, 2.0)
self.assertAlmostEqual(b.p.flux, 5.0)
self.assertAlmostEqual(b.p.pdens, 0.5)

Expand Down
16 changes: 0 additions & 16 deletions armi/resources/coveragerc

This file was deleted.

63 changes: 55 additions & 8 deletions armi/settings/caseSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import logging
import os
from copy import copy, deepcopy
from ruamel.yaml import YAML

from armi import context
from armi import runLog
Expand Down Expand Up @@ -357,24 +358,70 @@ def writeToYamlFile(self, fName, style="short"):
Notes
-----
This resets the current CS's path to the newly written path.
This resets the current CS's path to the newly written absolute path.
Parameters
----------
fName : str
the file to write to
style : str
the method of output to be used when creating the file for
the current state of settings
style : str (optional)
the method of output to be used when creating the file for the current
state of settings
"""
self.path = pathTools.armiAbsPath(fName)
if style == "medium":
settingsSetByUser = self.getSettingsSetByUser(self.path)
else:
settingsSetByUser = []
with open(self.path, "w") as stream:
writer = self.writeToYamlStream(stream, style)
writer = self.writeToYamlStream(stream, style, settingsSetByUser)
return writer

def writeToYamlStream(self, stream, style="short"):
"""Write settings in yaml format to an arbitrary stream."""
writer = settingsIO.SettingsWriter(self, style=style)
def getSettingsSetByUser(self, fPath):
"""
Grabs the list of settings in the user-defined input file so that the settings
can be tracked outside of a Settings Object
Parameters
----------
fPath : str
The absolute file path of the settings file
Returns
-------
userSettingsNames : list
The settings names read in from a yaml settings file
"""

# We do not want to load these as settings, but just grab the dictionary straight
# from the settings file to know which settings are user-defined
with open(fPath, "r") as stream:
yaml = YAML()
tree = yaml.load(stream)
userSettings = tree[settingsIO.Roots.CUSTOM]
userSettingsNames = list(userSettings.keys())
return userSettingsNames

def writeToYamlStream(self, stream, style="short", settingsSetByUser=[]):
"""
Write settings in yaml format to an arbitrary stream.
Parameters
----------
stream : file object
Writable file stream
style : str (optional)
Writing style for settings file. Can be short, medium, or full.
settingsSetByUser : list
List of settings names in user-defined settings file
Returns
-------
writer : SettingsWriter object
"""
writer = settingsIO.SettingsWriter(
self, style=style, settingsSetByUser=settingsSetByUser
)
writer.writeYaml(stream)
return writer

Expand Down
Loading

0 comments on commit 5dbf670

Please sign in to comment.