Source code for armi.physics.neutronics.settings

# 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.physics.neutronics import LatticePhysicsFrequency
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_RUN_TYPE,
)


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"
CONF_LATTICE_PHYSICS_FREQUENCY = "latticePhysicsFrequency"


[docs]def defineSettings(): """Standard function to define settings; for neutronics. .. impl:: Users to select if gamma cross sections are generated. :id: I_ARMI_GAMMA_XS :implements: R_ARMI_GAMMA_XS A single boolean setting can be used to turn on/off the calculation of gamma cross sections. This is implemented with the usual boolean ``Setting`` logic. The goal here is performance; save the compute time if the analyst doesn't need those cross sections. """ 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 in the working directory, but fail if there is no ISOTXS.", 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", ], enforcedOptions=True, ), 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="Is this 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 considered for " "computing macroscopic cross sections. It can also be passed to physics " "plugins.", ), 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="Average", 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_LATTICE_PHYSICS_FREQUENCY, default="BOC", label="Frequency of lattice physics updates", description="Define the frequency at which cross sections are updated with " "new lattice physics interactions.", options=[opt.name for opt in list(LatticePhysicsFrequency)], enforcedOptions=True, ), 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_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, ), ) ) queryMsg = ( "A Snapshots case is selected but the `latticePhysicsFrequency` " "{0} is less than `firstCoupledIteration`. `firstCoupledIteration`" " or `all` is recommended for Snapshots when they involve large changes " "in power or flow compared to the loaded state." ).format(inspector.cs[CONF_LATTICE_PHYSICS_FREQUENCY]) queryPrompt = ( "Would you like to update `latticePhysicsFrequency` from " f"{inspector.cs[CONF_LATTICE_PHYSICS_FREQUENCY]} to `firstCoupledIteration`?" ) queries.append( settingsValidation.Query( lambda: inspector.cs[CONF_RUN_TYPE] == "Snapshots" and not LatticePhysicsFrequency[ inspector.cs[CONF_LATTICE_PHYSICS_FREQUENCY] ] >= LatticePhysicsFrequency.firstCoupledIteration, queryMsg, queryPrompt, lambda: inspector._assignCS( CONF_LATTICE_PHYSICS_FREQUENCY, "firstCoupledIteration" ), ) ) return queries