# Copyright 2019 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Some generic neutronics-related settings"""
import os
from armi import runLog
from armi.operators import settingsValidation
from armi.physics.neutronics.const import NEUTRON
from armi.physics.neutronics.energyGroups import GROUP_STRUCTURE
from armi.scripts.migration.crossSectionBlueprintsToSettings import (
migrateCrossSectionsFromBlueprints,
)
from armi.settings import setting
from armi.utils import directoryChangers
from armi.settings.fwSettings.globalSettings import (
CONF_DETAILED_AXIAL_EXPANSION,
CONF_NON_UNIFORM_ASSEM_FLAGS,
)
CONF_BC_COEFFICIENT = "bcCoefficient"
CONF_BOUNDARIES = "boundaries"
CONF_DPA_PER_FLUENCE = "dpaPerFluence"
CONF_EIGEN_PROB = "eigenProb"
CONF_EPS_EIG = "epsEig"
CONF_EPS_FSAVG = "epsFSAvg"
CONF_EPS_FSPOINT = "epsFSPoint"
CONF_EXISTING_FIXED_SOURCE = "existingFixedSource"
CONF_GEN_XS = "genXS" # gamma stuff and neutronics plugin/lattice physics
CONF_GLOBAL_FLUX_ACTIVE = "globalFluxActive"
CONF_GROUP_STRUCTURE = "groupStructure"
CONF_INNERS_ = "inners"
CONF_LOADING_FILE = "loadingFile"
CONF_NEUTRONICS_KERNEL = "neutronicsKernel"
CONF_NEUTRONICS_TYPE = "neutronicsType"
CONF_NUMBER_MESH_PER_EDGE = "numberMeshPerEdge"
CONF_OUTERS_ = "outers"
CONF_RESTART_NEUTRONICS = "restartNeutronics"
# Used for dpa/dose analysis.
# TODO: These should be relocated to more design-specific places
CONF_ACLP_DOSE_LIMIT = "aclpDoseLimit"
CONF_DPA_XS_SET = "dpaXsSet"
CONF_GRID_PLATE_DPA_XS_SET = "gridPlateDpaXsSet"
CONF_LOAD_PAD_ELEVATION = "loadPadElevation"
CONF_LOAD_PAD_LENGTH = "loadPadLength"
CONF_OPT_DPA = [
"",
"dpa_EBRII_INC600",
"dpa_EBRII_INCX750",
"dpa_EBRII_HT9",
"dpa_EBRII_PE16",
"dpa_EBRII_INC625",
]
# moved from xsSettings
CONF_CLEAR_XS = "clearXS"
CONF_MINIMUM_FISSILE_FRACTION = "minimumFissileFraction"
CONF_MINIMUM_NUCLIDE_DENSITY = "minimumNuclideDensity"
CONF_INFINITE_DILUTE_CUTOFF = "infiniteDiluteCutoff"
CONF_TOLERATE_BURNUP_CHANGE = "tolerateBurnupChange"
CONF_XS_BLOCK_REPRESENTATION = "xsBlockRepresentation"
CONF_DISABLE_BLOCK_TYPE_EXCLUSION_IN_XS_GENERATION = (
"disableBlockTypeExclusionInXsGeneration"
)
CONF_XS_KERNEL = "xsKernel"
CONF_XS_SCATTERING_ORDER = "xsScatteringOrder"
CONF_XS_BUCKLING_CONVERGENCE = "xsBucklingConvergence"
CONF_XS_EIGENVALUE_CONVERGENCE = "xsEigenvalueConvergence"
[docs]def defineSettings():
"""standard function to define settings - for neutronics"""
settings = [
setting.Setting(
CONF_GROUP_STRUCTURE,
default="ANL33",
label="Number of Energy Groups",
description="Energy group structure to use in neutronics simulations",
options=[
"ANL9",
"ANL33",
"ANL70",
"ANL116",
"ANL230",
"ANL703",
"ANL1041",
"ANL2082",
"ARMI33",
"ARMI45",
"CINDER63",
"348",
],
),
setting.Setting(
CONF_GLOBAL_FLUX_ACTIVE,
default="Neutron",
label="Global Flux Calculation",
description="Calculate the global flux at each timestep for the selected "
"particle type(s) using the specified neutronics kernel (see Global Flux "
"tab).",
options=["", "Neutron", "Neutron and Gamma"],
),
setting.Setting(
CONF_GEN_XS,
default="",
label="Multigroup Cross Sections Generation",
description="Generate multigroup cross sections for the selected particle "
"type(s) using the specified lattice physics kernel (see Lattice Physics "
"tab). When not set, the XS library will be auto-loaded from an existing ISOTXS "
"within then working directory and fail if the ISOTXS does not exist.",
options=["", "Neutron", "Neutron and Gamma"],
),
setting.Setting(
CONF_DPA_PER_FLUENCE,
default=4.01568627451e-22,
label="DPA Per Fluence",
description="A quick and dirty conversion that is used to get "
"dpaPeak by multiplying the factor and fastFluencePeak",
),
setting.Setting(
CONF_BC_COEFFICIENT,
default=0.0,
label="Parameter A for generalized BC",
description="Value for the parameter A of the generalized boundary "
"condition.",
),
setting.Setting(
CONF_BOUNDARIES,
default="Extrapolated",
label="Neutronic BCs",
description="External Neutronic Boundary Conditions. Reflective does not "
"include axial.",
options=[
"Extrapolated",
"Reflective",
"Infinite",
"ZeroSurfaceFlux",
"ZeroInwardCurrent",
"Generalized",
],
),
setting.Setting(
CONF_NEUTRONICS_KERNEL,
default="",
label="Neutronics Kernel",
description="The neutronics / depletion solver for global flux solve.",
options=[],
enforcedOptions=True,
),
setting.Setting(
CONF_NEUTRONICS_TYPE,
default="real",
label="Neutronics Type",
description="The type of neutronics solution that is desired.",
options=["real", "adjoint", "both"],
),
setting.Setting(
CONF_EIGEN_PROB,
default=True,
label="Eigenvalue Problem",
description="Whether this is a eigenvalue problem or a fixed source problem",
),
setting.Setting(
CONF_EXISTING_FIXED_SOURCE,
default="",
label="Existing fixed source input",
description="Specify an exiting fixed source input file.",
options=["", "FIXSRC", "VARSRC"],
),
setting.Setting(
CONF_NUMBER_MESH_PER_EDGE,
default=1,
label="Number of Mesh per Edge",
description="Number of mesh per block edge for finite-difference planar "
"mesh refinement.",
oldNames=[("hexSideSubdivisions", None)],
),
setting.Setting(
CONF_EPS_EIG,
default=1e-07,
label="Eigenvalue Epsilon",
description="Convergence criteria for calculating the eigenvalue in the global flux solver",
),
setting.Setting(
CONF_EPS_FSAVG,
default=1e-05,
label="FS Avg. epsilon",
description="Convergence criteria for average fission source",
),
setting.Setting(
CONF_EPS_FSPOINT,
default=1e-05,
label="FS Point epsilon",
description="Convergence criteria for point fission source",
),
setting.Setting(
CONF_LOAD_PAD_ELEVATION,
default=0.0,
label="Load pad elevation (cm)",
description=(
"The elevation of the bottom of the above-core load pad (ACLP) in cm "
"from the bottom of the upper grid plate. Used for calculating the load "
"pad dose"
),
),
setting.Setting(
CONF_LOAD_PAD_LENGTH,
default=0.0,
label="Load pad length (cm)",
description="The length of the load pad. Used to compute average and peak dose.",
),
setting.Setting(
CONF_ACLP_DOSE_LIMIT,
default=80.0,
label="ALCP dose limit",
description="Dose limit in dpa used to position the above-core load pad (if one exists)",
),
setting.Setting(
CONF_RESTART_NEUTRONICS,
default=False,
label="Restart neutronics",
description="Restart global flux case using outputs from last time as a guess",
),
setting.Setting(
CONF_OUTERS_,
default=100,
label="Max Outer Iterations",
description="XY and Axial partial current sweep max outer iterations.",
),
setting.Setting(
CONF_INNERS_,
default=0,
label="Inner Iterations",
description="XY and Axial partial current sweep inner iterations. 0 lets the neutronics code pick a default.",
),
setting.Setting(
CONF_GRID_PLATE_DPA_XS_SET,
default="dpa_EBRII_HT9",
label="Grid plate DPA XS",
description=(
"The cross sections to use for grid plate blocks DPA when computing "
"displacements per atom."
),
options=CONF_OPT_DPA,
),
setting.Setting(
CONF_DPA_XS_SET,
default="dpa_EBRII_HT9",
label="DPA Cross Sections",
description="The cross sections to use when computing displacements per atom.",
options=CONF_OPT_DPA,
),
setting.Setting(
CONF_CLEAR_XS,
default=False,
label="Clear XS",
description="Delete all cross section libraries before regenerating them.",
),
setting.Setting(
CONF_MINIMUM_FISSILE_FRACTION,
default=0.045,
label="Minimum Fissile Fraction",
description="Minimum fissile fraction (fissile number densities / heavy metal number densities).",
oldNames=[("mc2.minimumFissileFraction", None)],
),
setting.Setting(
CONF_MINIMUM_NUCLIDE_DENSITY,
default=1e-15,
label="Minimum nuclide density",
description="Density to use for nuclides and fission products at infinite dilution. This is also used as the minimum density.",
),
setting.Setting(
CONF_INFINITE_DILUTE_CUTOFF,
default=1e-10,
label="Infinite Dillute Cutoff",
description="Do not model nuclides with density less than this cutoff. Used with PARTISN and SERPENT.",
),
setting.Setting(
CONF_TOLERATE_BURNUP_CHANGE,
default=0.0,
label="Cross Section Burnup Group Tolerance",
description="Burnup window for computing cross sections. If the prior cross sections were computed within the window, new cross sections will not be generated and the prior calculated cross sections will be used.",
),
setting.Setting(
CONF_XS_BLOCK_REPRESENTATION,
default="FluxWeightedAverage",
label="Cross Section Block Averaging Method",
description="The type of averaging to perform when creating cross sections for a group of blocks",
options=[
"Median",
"Average",
"FluxWeightedAverage",
"ComponentAverage1DSlab",
],
),
setting.Setting(
CONF_DISABLE_BLOCK_TYPE_EXCLUSION_IN_XS_GENERATION,
default=False,
label="Include All Block Types in XS Generation",
description="Use all blocks in a cross section group when generating a representative block. When this is disabled only `fuel` blocks will be considered",
),
setting.Setting(
CONF_XS_KERNEL,
default="MC2v3",
label="Lattice Physics Kernel",
description="Method to determine broad group cross sections for assemblies",
options=["", "MC2v2", "MC2v3", "MC2v3-PARTISN", "SERPENT"],
),
setting.Setting(
CONF_XS_SCATTERING_ORDER,
default=3,
label="Scattering Order",
description="Scattering order for the lattice physics calculation",
),
setting.Setting(
CONF_XS_BUCKLING_CONVERGENCE,
default=1e-05,
label="Buckling Convergence Criteria",
description="Convergence criteria for the buckling iteration if it is available in the lattice physics solver",
oldNames=[
("mc2BucklingConvergence", None),
("bucklingConvergence", None),
],
),
setting.Setting(
CONF_XS_EIGENVALUE_CONVERGENCE,
default=1e-05,
label="Eigenvalue Convergence Criteria",
description="Convergence criteria for the eigenvalue in the lattice physics kernel",
),
]
return settings
def _blueprintsHasOldXSInput(inspector):
path = inspector.cs[CONF_LOADING_FILE]
with directoryChangers.DirectoryChanger(inspector.cs.inputDirectory):
with open(os.path.expandvars(path)) as f:
for line in f:
if line.startswith("cross sections:"):
return True
return False
[docs]def getNeutronicsSettingValidators(inspector):
"""The standard helper method, to provide validators to neutronics settings"""
queries = []
def migrateXSOption(name0):
"""
The `genXS` and `globalFluxActive` settings used to take True/False as inputs,
this helper method migrates those to the new values.
"""
value = inspector.cs[name0]
if value == "True":
value = NEUTRON
elif value == "False":
value = ""
inspector.cs = inspector.cs.modified(newSettings={name0: value})
def migrateXSOptionGenXS():
"""pass-through to migrateXSOption(), because Query functions cannot take arguements"""
migrateXSOption(CONF_GEN_XS)
def migrateXSOptionGlobalFluxActive():
"""pass-through to migrateXSOption(), because Query functions cannot take arguements"""
migrateXSOption(CONF_GLOBAL_FLUX_ACTIVE)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_GEN_XS] in ("True", "False"),
"The {0} setting cannot not take `True` or `False` as an exact value any more.",
'Would you like to auto-correct {0} to the correct value? ("" or {1})'.format(
CONF_GEN_XS, NEUTRON
),
migrateXSOptionGenXS,
)
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_GLOBAL_FLUX_ACTIVE] in ("True", "False"),
"The {0} setting cannot not take `True` or `False` as an exact value any more.",
'Would you like to auto-correct {0} to the correct value? ("" or {1})'.format(
CONF_GLOBAL_FLUX_ACTIVE, NEUTRON
),
migrateXSOptionGlobalFluxActive,
)
)
def migrateNormalBCSetting():
"""The `boundary` setting is migrated from `Normal` to `Extrapolated`."""
inspector.cs = inspector.cs.modified(
newSettings={CONF_BOUNDARIES: "Extrapolated"}
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_BOUNDARIES] == "Normal",
"The {0} setting now takes `Extrapolated` instead of `Normal` as a value.".format(
CONF_BOUNDARIES
),
"Would you like to auto-correct {0} from `Normal` to `Extrapolated`?".format(
CONF_BOUNDARIES
),
migrateNormalBCSetting,
)
)
def updateXSGroupStructure():
"""Trying to migrate to a valid XS group structure name"""
value = inspector.cs[CONF_GROUP_STRUCTURE]
newValue = value.upper()
if newValue in GROUP_STRUCTURE:
runLog.info(
"Updating the cross section group structure from {} to {}".format(
value, newValue
)
)
else:
newValue = inspector.cs.getSetting(CONF_GROUP_STRUCTURE).default
runLog.info(
"Unable to automatically convert the {} setting of {}. Defaulting to {}".format(
CONF_GROUP_STRUCTURE, value, newValue
)
)
inspector.cs = inspector.cs.modified(
newSettings={CONF_GROUP_STRUCTURE: newValue}
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_GROUP_STRUCTURE] not in GROUP_STRUCTURE,
"The given group structure {0} was not recognized.".format(
inspector.cs[CONF_GROUP_STRUCTURE]
),
"Would you like to auto-correct the group structure value?",
updateXSGroupStructure,
)
)
def migrateDpa(name0):
"""migrating some common shortened names for dpa XS sets"""
value = inspector.cs[name0]
if value == "dpaHT9_33":
value = "dpaHT9_ANL33_TwrBol"
elif value == "dpa_SS316":
value = "dpaSS316_ANL33_TwrBol"
inspector.cs = inspector.cs.modified(newSettings={name0: value})
def migrateDpaDpaXsSet():
"""pass-through to migrateDpa(), because Query functions cannot take arguements"""
migrateDpa(CONF_DPA_XS_SET)
def migrateDpaGridPlate():
"""pass-through to migrateDpa(), because Query functions cannot take arguements"""
migrateDpa(CONF_GRID_PLATE_DPA_XS_SET)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_DPA_XS_SET] in ("dpaHT9_33", "dpa_SS316"),
"It appears you are using a shortened version of the {0}.".format(
CONF_DPA_XS_SET
),
"Would you like to auto-correct this to the full name?",
migrateDpaDpaXsSet,
)
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_GRID_PLATE_DPA_XS_SET]
in ("dpaHT9_33", "dpa_SS316"),
"It appears you are using a shortened version of the {0}.".format(
CONF_GRID_PLATE_DPA_XS_SET
),
"Would you like to auto-correct this to the full name?",
migrateDpaGridPlate,
)
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_LOADING_FILE]
and _blueprintsHasOldXSInput(inspector),
"The specified blueprints input file '{0}' contains compound cross section settings. "
"".format(inspector.cs[CONF_LOADING_FILE]),
"Automatically move them to the settings file, {}? WARNING: if multiple settings files point "
"to this blueprints input you must manually update the others.".format(
inspector.cs.path
),
lambda: migrateCrossSectionsFromBlueprints(inspector.cs),
)
)
queries.append(
settingsValidation.Query(
lambda: inspector.cs[CONF_DETAILED_AXIAL_EXPANSION]
and inspector.cs[CONF_NON_UNIFORM_ASSEM_FLAGS],
f"The use of {CONF_DETAILED_AXIAL_EXPANSION} and {CONF_NON_UNIFORM_ASSEM_FLAGS} is not supported.",
"Automatically set non-uniform assembly treatment to its default?",
lambda: inspector._assignCS(
CONF_NON_UNIFORM_ASSEM_FLAGS,
inspector.cs.getSetting(CONF_NON_UNIFORM_ASSEM_FLAGS).default,
),
)
)
return queries