Example Input File

The input file example used here is taken from moltres/tests/twod_axi_coupled/auto_diff_rho.i. To run this input file from the command line, run (substituting the path to the moltres root directory for $moltres_root):

cd $moltres_root/tests/twod_axi_coupled
$moltres_root/moltres-opt -i auto_diff_rho.i

In serial, this job takes around 90 seconds on a 2.7 GHz machine. To run the job in parallel, execute:

mpirun -np 2 $moltres_root/moltres-opt -i auto_diff_rho.i

where the number of processors can be changed from 2 to however many processes you want to run. The parallel performance of the job depends on the number of degrees of freedom in the problem and the preconditioner used. A general rule of thumb for optimal scaling is not to go below 20k degrees of freedom per processor, otherwise communication becomes a performance drag. Additionally many preconditioners do not perform as well when spread over multiple processes as they lose access to “new” information. (See http://www.mcs.anl.gov/petsc/documentation/faq.html#slowerparallel for more discussion of this). This particular input file (auto_diff_rho.i) only has 8,697 degrees of freedom so communication is a factor; however, the executioner used is a direct solver which scales well. On the same 2.7 GHz machine, the solution times for 1-4 processors are given below.

  • Single processor solution time: 90 seconds
  • Two processors: 50 seconds
  • Three: 35 seconds
  • Four: 30 seconds

Before delving into a description of the input file, we note that all the parameter options for different input blocks can be seen by executing moltres-opt --dump.

Example output corresponding to the input file under discussion can be found in $moltres_root/tests/twod_axi_coupled/gold/auto_diff_rho.e. The most common application for visualizing output files is ParaView, although VisIt or yt may also be used.

Ok, running through the input file from the top:

flow_velocity=21.7 # cm/s. See MSRE-properties.ods
nt_scale=1e13
ini_temp=922
diri_temp=922

Variables defined at the top of an input file can be used throughout the remainder of the file with GetPot syntax. We will show later in the input file an example of the GetPot syntax. flow_velocity may be modified to affect our primary variables, temperature, neutron fluxes, and precursor concentrations. Decreasing flow velocity will increase the temperature increase through the reactor. Because of the negative feedback cofficients of fuel and moderator for this reactor composition (modeled after Oak Ridge’s MSRE), the increase in average reactor temperature decreases the total reactor power and consequently the neutron fluxes and precursor concentrations. Similarly, increasing the inlet temperature, controlled through diri_temp, decreases reactor power.

Following the GetPot variables definitions, we have the GlobalParams block:

[GlobalParams]
  num_groups = 2
  num_precursor_groups = 6
  use_exp_form = false
  group_fluxes = 'group1 group2'
  temperature = temp
  sss2_input = false
  pre_concs = 'pre1 pre2 pre3 pre4 pre5 pre6'
  account_delayed = true
[]

In GlobalParams, parameters like num_groups can be globally set to a value. Consequently any class (e.g. the kernel class GroupDiffusion) that has the parameter num_groups will read in a value of 2 unless it is overridden locally in its input block. It should be noted that the GlobalParams block and any other MOOSE input block can be placed anywhere in the input file; at execution time each block will be read when appropriate. Parameters description:

  • num_groups: The number of energy groups for neutron diffusion
  • num_precursor_groups: The number of delayed neutron precursor groups
  • use_exp_form: Whether the actual neutron/precursor fluxes/concentrations should be represented by or where is the actual variable value
  • group_fluxes: The names of the neutron group fluxes
  • temperature: The name of the temperature variable
  • sss2_input: True if the macroscopic group constants were generated by Serpent 2. False otherwise
  • pre_concs: The names of the precursor concentration variables
  • account_delayed: Whether to account for delayed neutron production. Modifies the neutron source term

Following GlobalParams in our example, we have the Mesh block:

[Mesh]
  file = '2d_lattice_structured.msh'
  # file = '2d_lattice_structured_jac.msh'
[]

Before describing the Mesh block, we note that comments in the Moltres input file can be introuduced with the # character. Any characters following the # character will not be read by the MOOSE parser.

The two most commonly used Mesh types are FileMesh and GeneratedMesh. The Mesh input block by default assumes type FileMesh and takes a parameter argument file = <mesh_file_name>. Many MOOSE users generate their meshes using Cubit/Trellis. For national lab employees this software is free; however, academic or industry users must pay. Consequently, Moltres meshes to date have been generated using the software gmsh which is free and open source. Binaries for Windows, Mac, and Linux as well as source code can be downloaded here. Ubuntu users may also install gmsh using sudo apt-get install gmsh. We will not go into the details of using gmsh but the interested user should peruse its documentation. There are many example gmsh input files in the Moltres repository (denoted by the .geo extension). To generate a mesh for use with Moltres, a typical bash command is gmsh -2 -o file_name.msh file_name.geo where 2 should be replaced with the dimension of the mesh, the argument following -o is the name of the output .msh file, and the last argument is the input .geo file.

Gmsh or Cubit can be used for generation of highly complex mesh structures. However, if the user just wishes to generate a simple mesh, he/she may use MOOSE’s built-in type GeneratedMesh. For using GeneratedMesh we refer the reader here.

Next in our example input file, we have the Problem block:

[Problem]
  coord_type = RZ
[]

The Problem block may usually be omitted from the input file for a Cartesian simulation. However, since this particular example is using 2D-axisymmetric coordinates, we have to convey this information using Problem’s coord_type parameter.

The Variables block introduces sub-blocks:

[Variables]
  [./group1]
    order = FIRST
    family = LAGRANGE
    initial_condition = 1
    scaling = 1e4
  [../]
  [./group2]
    order = FIRST
    family = LAGRANGE
    initial_condition = 1
    scaling = 1e4
  [../]
  [./temp]
    initial_condition = ${ini_temp}
    scaling = 1e-4
  [../]
[]

Sub-blocks are initialized with [./<object_name>] and closed with [../]. The group1 sub-block creates a MooseVariable object with the name group1. The family parameter describes the shape function type used to form the approximate finite element solution. The order parameter denotes the polynomial order of the shape functions. initial_condition is an optional parameter that can be used to set a spatially uniform initial value for the variable. scaling is another optional parameter that can be used to scale the residual of the corresponding variable; this is usually done when different variables have residuals of different orders of magnitude.

[Precursors]
  [./pres]
    var_name_base = pre
    block = 'fuel'
    outlet_boundaries = 'fuel_tops'
    u_def = 0
    v_def = ${flow_velocity}
    w_def = 0
    nt_exp_form = false
    family = MONOMIAL
    order = CONSTANT
    # jac_test = true
  [../]
[]

Whereas all the other blocks that have been introduced are standard MOOSE blocks, Precursors is a custom input file block unique to Moltres. The Precursors action creates all the precursor variables, kernels, and boundary conditions necessary for solving the precursor governing equations. Parameter descriptions:

  • var_name_base: The prefix for the precursor variable names. Name suffixes are numbers, e.g. pre1, pre2, ...
  • block: This is a parameter ubiquitous to many MOOSE classes such as kernels and materials. By specifying a value for block the user is asking that in this case, precursors and their associated governing equations only be solved for in the fuel mesh subdomains
  • outlet_boundaries: The mesh boundaries from which the precursors flow out
  • u_def, v_def, w_def: The x, y, and z components of velocity, or in the case of an RZ simulation, u_def is the r velocity component, v_def is the z-component, and w_def has no meaning
  • nt_exp_form: Whether the neutron group fluxes have their concentrations in an exponential form. If use_exp_form is false in the GlobalParams block, this should also be false
  • jac_test: true if testing the application developer’s jacobian against a jacobian formed through finite differencing of the residuals. Defaults to false.
[Kernels]
  # Neutronics
  [./time_group1]
    type = NtTimeDerivative
    variable = group1
    group_number = 1
  [../]
  [./diff_group1]
    type = GroupDiffusion
    variable = group1
    group_number = 1
  [../]
  [./sigma_r_group1]
    type = SigmaR
    variable = group1
    group_number = 1
  [../]
  [./fission_source_group1]
    type = CoupledFissionKernel
    variable = group1
    group_number = 1
    block = 'fuel'
  [../]
  [./delayed_group1]
    type = DelayedNeutronSource
    variable = group1
    block = 'fuel'
  [../]
  [./inscatter_group1]
    type = InScatter
    variable = group1
    group_number = 1
  [../]
  [./diff_group2]
    type = GroupDiffusion
    variable = group2
    group_number = 2
  [../]
  [./sigma_r_group2]
    type = SigmaR
    variable = group2
    group_number = 2
  [../]
  [./time_group2]
    type = NtTimeDerivative
    variable = group2
    group_number = 2
  [../]
  [./fission_source_group2]
    type = CoupledFissionKernel
    variable = group2
    group_number = 2
    block = 'fuel'
  [../]
  [./inscatter_group2]
    type = InScatter
    variable = group2
    group_number = 2
  [../]

  # Temperature
  [./temp_time_derivative]
    type = MatINSTemperatureTimeDerivative
    variable = temp
  [../]
  [./temp_source_fuel]
    type = TransientFissionHeatSource
    variable = temp
    nt_scale=${nt_scale}
    block = 'fuel'
  [../]
  # [./temp_source_mod]
  #   type = GammaHeatSource
  #   variable = temp
  #   gamma = .0144 # Cammi .0144
  #   block = 'moder'
  #   average_fission_heat = 'average_fission_heat'
  # [../]
  [./temp_diffusion]
    type = MatDiffusion
    D_name = 'k'
    variable = temp
  [../]
  [./temp_advection_fuel]
    type = ConservativeTemperatureAdvection
    velocity = '0 ${flow_velocity} 0'
    variable = temp
    block = 'fuel'
  [../]
[]

The Kernels block is pretty straightforward. The kernel type or class is specified with type = <kernel_type>. The mathematical representation of each Moltres kernel type can be found on the kernel wiki page. Each kernel contributes to the residual of the variable specified by variable = <variable_name>. Kernels can be optionally block restricted by setting block = <subdomain_names>.

[BCs]
  [./vacuum_group1]
    type = VacuumConcBC
    boundary = 'fuel_bottoms fuel_tops moder_bottoms moder_tops outer_wall'
    variable = group1
  [../]
  [./vacuum_group2]
    type = VacuumConcBC
    boundary = 'fuel_bottoms fuel_tops moder_bottoms moder_tops outer_wall'
    variable = group2
  [../]
  [./temp_diri_cg]
    boundary = 'moder_bottoms fuel_bottoms outer_wall'
    type = FunctionDirichletBC
    function = 'temp_bc_func'
    variable = temp
  [../]
  [./temp_advection_outlet]
    boundary = 'fuel_tops'
    type = TemperatureOutflowBC
    variable = temp
    velocity = '0 ${flow_velocity} 0'
  [../]
[]

The BCs block is very similar to the Kernels block except the boundary = <boundary_names> parameter must be specified to indicate where the boundary conditions should be applied. The mathematical form of the BCs can be found on the BCs wiki page.

[Functions]
  [./temp_bc_func]
    type = ParsedFunction
    value = '${ini_temp} - (${ini_temp} - ${diri_temp}) * tanh(t/1e-2)'
  [../]
[]

The Functions block is necessary when other MOOSE/Moltres objects specified in the input file require functions. In this example we have a boundary condition object temp_diri_cg of type FunctionDirichletBC that requires a function object to specify the values of the variable temp along the reactor boundaries. We name this function object temp_bc_func and specify it to be of type ParsedFunction which is a function type that can be written in terms of constants and the independent variables and . Here we see the use of GetPot syntax ${<variable_name>}$ to access the values of ini_temp and diri_temp specified at the top of the input file.

[Materials]
  [./fuel]
    type = GenericMoltresMaterial
    property_tables_root = '../property_file_dir/newt_msre_fuel_'
    interp_type = 'spline'
    block = 'fuel'
    prop_names = 'k cp'
    prop_values = '.0553 1967' # Robertson MSRE technical report @ 922 K
  [../]
  [./rho_fuel]
    type = DerivativeParsedMaterial
    f_name = rho
    function = '2.146e-3 * exp(-1.8 * 1.18e-4 * (temp - 922))'
    args = 'temp'
    derivative_order = 1
    block = 'fuel'
  [../]
  [./moder]
    type = GenericMoltresMaterial
    property_tables_root = '../property_file_dir/newt_msre_mod_'
    interp_type = 'spline'
    prop_names = 'k cp'
    prop_values = '.312 1760' # Cammi 2011 at 908 K
    block = 'moder'
  [../]
  [./rho_moder]
    type = DerivativeParsedMaterial
    f_name = rho
    function = '1.86e-3 * exp(-1.8 * 1.0e-5 * (temp - 922))'
    args = 'temp'
    derivative_order = 1
    block = 'moder'
  [../]
[]

In the Materials block we specify materials that live on a mesh subdomain. Any given subdomain can have as many materials as desired. An important material in Moltres is GenericMoltresMaterial. Its parameters:

  • property_tables_root: The path and prefix of the files that contain the macroscopic group constants that define neutron reaction rates. The suffix of these files identifies the property that each conveys. For example the file containing the fuel fission cross sections is in this example newt_msre_fuel_FISSXS.txt. Each of these files contains an interpolation table. The left column (column 1) is temperature. The remaining columns contain the macroscopic constants for different energy groups corresponding to the tabulated temperature, e.g. column 2 contains the constants for energy group 1, column 3 contains the constants for energy group 2, etc. The set of tables used in this example were generated with NEWT, part of the SCALE code system. Serpent, OpenMC, or any other macroscopic cross section generator may be used to create these simple input tables.
  • interp_type: The type of fitting/interpolation to be carried out on the temperature grid. Options are:
    • bicubic_spline: Done when macroscopic constants are a function of the temperature of the local material as well as the average temperature of the other material
    • spline: Most common option used for monovariate interpolation between temperature knots
    • least_squares: Constructs a linear fit function of macroscopic constants as a function of temperature. Useful when group constant interpolation table is not monotonic
    • none: Only should be used when single values for constants are supplied at a single temperature
  • prop_names, prop_values: name-value pairs used to define material property values from the input file. In this example, both the thermal conductivity and the specific heat capacity are defined from the input file for both fuel and moderator subdomains.

DerivativeParsedMaterial is a material inherited from the Phase Field module of the MOOSE framework. Its useful for creating material properties that are functions of solution variables and for coupling the dependency of the property on the variable back into the Jacobian used for Newton-Raphson. A more in-depth description of the material along with its relatives is given here.

Users can exert their greatest influence on the calculations through the Materials block. Increasing values of rho or cp will increase materials ability to store heat, enabling a greater reactor power. Because of application of an insulating boundary condition at the outer reactor wall in this example, modifying the thermal conductivity k has only a small impact on the simulation. However, if the conductivity is lowered by several orders of magnitude, the user will observe increases in radial gradients between the fuel channels and graphite as well as a decrease in reactor power. Use of different macroscopic group constant tables or direct modification of the current set would also influence simulation results.

[Executioner]
  type = Transient
  end_time = 10000

  nl_rel_tol = 1e-6
  nl_abs_tol = 1e-6

  solve_type = 'NEWTON'
  petsc_options = '-snes_converged_reason -ksp_converged_reason -snes_linesearch_monitor'
  petsc_options_iname = '-pc_type -pc_factor_shift_type -pc_factor_shift_amount -ksp_type -snes_linesearch_minlambda'
  petsc_options_value = 'lu       NONZERO               1e-10                   preonly   1e-3'
  line_search = 'none'
   # petsc_options_iname = '-snes_type'
  # petsc_options_value = 'test'

  nl_max_its = 30
  l_max_its = 100

  dtmin = 1e-5
  # dtmax = 1
  # dt = 1e-3
  [./TimeStepper]
    type = IterationAdaptiveDT
    dt = 1e-3
    cutback_factor = 0.4
    growth_factor = 1.2
    optimal_iterations = 20
  [../]
[]

[Preconditioning]
  [./SMP]
    type = SMP
    full = true
	ksp_norm = none
  [../]
[]

The Executioner and Preconditioning blocks are essential to determining the method used to solve the system of non-linear equations created by finite element discretization of our molten salt reactor governing equations. Executioner and Preconditioning documentation can be found here and here respectively.

[Postprocessors]
  [./group1_current]
    type = IntegralNewVariablePostprocessor
    variable = group1
    outputs = 'console exodus'
  [../]
  [./group1_old]
    type = IntegralOldVariablePostprocessor
    variable = group1
    outputs = 'console exodus'
  [../]
  [./multiplication]
    type = DivisionPostprocessor
    value1 = group1_current
    value2 = group1_old
    outputs = 'console exodus'
  [../]
  [./temp_fuel]
    type = ElementAverageValue
    variable = temp
    block = 'fuel'
    outputs = 'exodus console'
  [../]
  [./temp_moder]
    type = ElementAverageValue
    variable = temp
    block = 'moder'
    outputs = 'exodus console'
  [../]
  # [./average_fission_heat]
  #   type = AverageFissionHeat
  #   nt_scale = ${nt_scale}
  #   execute_on = 'linear nonlinear'
  #   outputs = 'console'
  #   block = 'fuel'
  # [../]
[]

General postprocessor documentation can be found here. In this example, the first three postprocessors group1_current, group1_old and multiplication are used to calculate the neutron multiplication between current and old timesteps. The IntegralNewVariablePostprocessor integrates the supplied variable’s value over the entire domain at the current time step. The IntegralOldVariablePostprocessor does the same thing but for the previous time-step. The DivisionPostprocessor then divides value1 by value2. The ElementAverageValue postprocessor simply calculates the average value of a variable over an optionally restricted domain. AverageFissionHeat, commented out in this example, determines the average volumetric fission heating rate over a domain. This has been used to implement gamma radiation heating in the moderator as some fraction of the average fission heat produced in the fuel.

[Outputs]
  print_perf_log = true
  print_linear_residuals = true
  [./exodus]
    type = Exodus
    file_base = 'auto_diff_rho'
    execute_on = 'final'
  [../]
[]

Outputs documentation is here.

[Debug]
  show_var_residual_norms = true
[]

This simply tells our executable to print the variable residual norms during the non-linear solve.

# [ICs]
#   [./temp_ic]
#     type = RandomIC
#     variable = temp
#     min = 922
#     max = 1022
#   [../]
#   [./group1_ic]
#     type = RandomIC
#     variable = group1
#     min = .5
#     max = 1.5
#   [../]
#   [./group2_ic]
#     type = RandomIC
#     variable = group2
#     min = .5
#     max = 1.5
#   [../]
# []

The ICs block can be used to construct variable initial conditions. Documentation is here. The commented out ICs in this particular file are sometimes used to test the Jacobians of new kernels and boundary conditions introduced into Moltres.