Pronghorn thermal hydraulics steady state for gFHR
Contact: Dr. Mustafa Jaradat, [email protected]
Sponsor: Dr. Steve Bajorek (NRC)
Model summarized, documented, and uploaded by Dr. Mustafa Jaradat and Dr. Samuel Walker
Pronghorn is the thermal hydraulics solver we use to simulate fluid flow and conjugate heat transfer in the gFHR core. In the same input file, we model the heat transfer in the solid phase in the core and heat conduction in the solid components around the core, for a total of five equations: conservation of mass, x- and y-momentum (in RZ coordinates), fluid and solid energy.
We are using the finite volume capabilities in MOOSE to model all these physics. We use an weakly-compressible approximation for the fluid flow. There are various closures used in the pebble bed for the heat transfer coefficients, the drag models, which are detailed in the Pronghorn manual. For a more detailed analyses of the specific Navier-Stokes equations that are solved for FHRs please see the Mark 1 Pronghorn Model.
Problem Parameters
We first define in the input file header physical quantities such as the core geometry, hydraulic diameters of flow paths, porosities, interpolation methods, core power, fluid blocks, heat transfer coefficients, and a Forcheimer friction coefficient.
# ------------------------------------------------------------------------------
# Description:
# gFHR input
# gFHR salt simulation
# Porous Flow Weakly Compressible Media Finite Volume
# sprvel: superficial formulation of the velocities
# ------------------------------------------------------------------------------
# THIS INPUT IS THE FULL-PHYSICS VERSION
# ------------------------------------------------------------------------------
# Set the conductivity type using the Pronghorn model
pebble_bed_fluid_effective_conductivity_type=FunctorLinearPecletKappaFluid
# Include common input shared between full simulation and testing version
!include gFHR_pronghorn_ss_base.i
# Set a parameter specifically required by the FunctorLinearPecletKappaFluid conductivity type
FunctorMaterials/pebble_bed_fluid_effective_conductivity/porosity=porosity_energy
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Global Parameters & Debug Block
We also define a few global parameters that will be added to every block that may use them. This is done to reduce the length of the input file and improve its readability.
Here we set the pebble diameter, fluid properties, pressure, interpolation methods, density, acceleration, and Rhie-Chow user object.
[GlobalParams]
pebble_diameter = ${pebble_diameter}
fp = fluid_properties
pressure = pressure
# FV parameters
two_term_boundary_expansion = true
advected_interp_method = ${advected_interp_method}
velocity_interp_method = ${velocity_interp_method}
rho = 'rho'
force_define_density = true
acceleration = '0.0 -9.8 0.0'
rhie_chow_user_object = 'pins_rhie_chow_interpolator'
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Additionally, there's a very short Debug
block which simply specifies that we want the variable residual norms to be showed in the output as the model runs.
[Debug]
show_var_residual_norms = true
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Mesh and geometry
The mesh input is standardized across MOOSE applications. The Mesh block is different from the one we saw for Griffin since the thermal-hydraulic mesh incorporates flow paths that go beyond the core. Similarly, we use the CartesianMeshGenerator
to make our mesh. Then we generate side-sets to define boundaries using SideSetsAroundSubdomainGenerator
and SideSetsBetweenSubdomainsGenerator
.
The thermal-hydraulic mesh is shown in Figure 1.

Figure 1: Pronghorn thermal fluids mesh from (Ortensi et al., 2023).
[Mesh]
block_id = ' 1 2 3 4 5 6 7 8 9 10 12 13 14 20 21 ' #30 is a buffer layer to protect the porosity smoothing and ensure conservation
block_name = 'flow1 flow2 flow3 flow4 flow5 dio1 dio2 dio3 flowp reflector barrel vessel1 vessel2 inlet outlet'
coord_type = RZ
rz_coord_axis = Y
[cartesian_mesh]
type = CartesianMeshGenerator
dim = 2
# keep mesh in the pebble bed roughly 3xpebble diameter ~12 cm for gFHR
dx = '0.8 0.1 0.3 0.2 0.2 0.2 0.02 0.05 0.04'
ix = ' 6 1 3 2 2 2 1 2 1'
dy = '0.04 0.05 0.3 0.3 0.154735 2.78523 0.154735 0.6 0.5 0.05 0.1 0.2 0.4'
iy = ' 1 2 2 2 1 18 1 4 4 2 1 2 2'
subdomain_id = '
14 13 13 13 13 13 13 13 13
2 1 1 1 1 1 1 1 13
2 2 10 10 10 10 12 1 13
2 2 9 10 10 10 12 1 13
3 3 3 10 10 10 12 1 13
3 3 3 10 10 10 12 1 13
3 3 3 10 10 10 12 1 13
4 9 5 10 10 10 12 1 13
4 10 5 10 10 10 12 1 13
4 10 5 6 7 8 8 1 13
4 10 10 10 10 10 12 1 13
4 10 10 10 10 10 12 1 20
21 10 10 10 10 10 12 12 13'
[]
[CL_SS]
type = SideSetsAroundSubdomainGenerator
input = cartesian_mesh
fixed_normal = true
normal = '-1 0 0'
block = '2 3 4 14 21'
new_boundary = 'centerline'
[]
[Inlet]
type = SideSetsAroundSubdomainGenerator
input = CL_SS
fixed_normal = true
normal = '1 0 0'
block = '20'
new_boundary = 'inlet'
[]
[Outlet]
type = SideSetsAroundSubdomainGenerator
input = Inlet
fixed_normal = true
normal = '0 1 0'
block = '21'
new_boundary = 'outlet'
[]
[vertical_walls_01]
type = SideSetsBetweenSubdomainsGenerator
input = Outlet
primary_block = '1 20'
paired_block = 13
new_boundary = wall1
[]
[vertical_walls_02]
type = SideSetsBetweenSubdomainsGenerator
input = vertical_walls_01
primary_block = 2
paired_block = 14
new_boundary = wall1
[]
[vertical_walls_03]
type = SideSetsBetweenSubdomainsGenerator
input = vertical_walls_02
primary_block = '1 8'
paired_block = 12
new_boundary = wall1
[]
[vertical_walls_04]
type = SideSetsBetweenSubdomainsGenerator
input = vertical_walls_03
primary_block = '1 2 3 4 5 6 7 8 9 21'
paired_block = 10
new_boundary = wall1
[]
[RCSS_Boundary]
type = SideSetsAroundSubdomainGenerator
input = vertical_walls_04
fixed_normal = true
include_only_external_sides = true
block = '13 14'
normal = '1 0 0'
new_boundary = RCSS
[]
[Mass_Flow_Sensor_1]
type = SideSetsBetweenSubdomainsGenerator
input = RCSS_Boundary
primary_block = '6'
paired_block = 7
new_boundary = MF_1
[]
[Mass_Flow_Sensor_2]
type = SideSetsBetweenSubdomainsGenerator
input = Mass_Flow_Sensor_1
primary_block = '7'
paired_block = 8
new_boundary = MF_2
[]
[Mass_Flow_Sensor_3]
type = SideSetsBetweenSubdomainsGenerator
input = Mass_Flow_Sensor_2
primary_block = '1'
paired_block = 2
new_boundary = MF_3
[]
uniform_refine = 0
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Physics - Navier Stokes Finite Volume Physics
Next we introduce a simplified approach to solving the thermal-hydraulic equations using the Navier Stokes Finite Volume Physics
The Physics directly set up the numerical form of the thermal-hydraulic equations that will be solved rather than making the user define every single kernel explicitly. In this case the action uses a weakly-compressible
formulation of the Navier-Stokes equations and adds in porous_medium_treatment
to model flow through the graphite pebbles.
Boundary conditions are set here, with no slip wall_boundaries
, inlet_boundaries
, and outlet_boundaries
where in fluid dynamics fashion, the inlet is a fixed-velocity
, and the outlet is a fixed-pressure
.
The heat convection from blocks to the coolant is defined in the ambient_convection
section. Friction factors using the darcy and forchheimer friction factors are also read into the equations here. Lastly, the remaining advection interpolation methods for momentum and mass are defined as well.
A Physics
is set up for every equation that is being solved. The Physics
communicate with each other to verify their parameters to some extent, attempting to minimize the number of errors. The equations being solved here are:
the mass and momentum equations by the
Flow
Physics
[Physics]
[NavierStokes]
[Flow]
[salt]
# General parameters
compressibility = 'weakly-compressible'
porous_medium_treatment = true
block = ${blocks_fluid}
gravity = '0 -9.81 0'
# Initial conditions
initial_pressure = 1e5
initial_velocity = '1e-10 1e-10 0'
# Variables
velocity_variable = 'superficial_vel_x superficial_vel_y'
pressure_variable = 'pressure'
# Wall boundary conditions
wall_boundaries = 'wall1'
momentum_wall_types = 'slip'
# Inlet boundary conditions
inlet_boundaries = 'inlet'
momentum_inlet_types = 'fixed-velocity'
momentum_inlet_functors = '-0.242984118 0'
# Outlet boundary conditions
outlet_boundaries = 'outlet'
momentum_outlet_types = 'fixed-pressure'
pressure_functors = 'Outlet_Average_Pressure_Function'
# Friction in porous media
friction_types = 'darcy forchheimer'
friction_coeffs = 'combined_linear combined_quadratic'
use_friction_correction = True
consistent_scaling = 200
# porosity_smoothing_layers = 8
# Numerical scheme
momentum_advection_interpolation = 'upwind'
mass_advection_interpolation = 'upwind'
[]
[]
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)the fluid energy conservation equation by the
FluidHeatTransfer
Physics
[Physics]
[NavierStokes]
[FluidHeatTransfer]
[salt]
fluid_temperature_variable = 'T_fluid'
initial_temperature = 823.14
block = ${blocks_fluid}
energy_inlet_types = 'fixed-temperature'
energy_inlet_functors = 'Inlet_Temperature_BC'
# Wall convection is modeled with a volumetric term
energy_wall_types = 'heatflux'
energy_wall_functors = '0'
thermal_conductivity = 'kappa'
effective_conductivity = false
# Porous flow parameters
ambient_convection_blocks = ${blocks_fluid}
ambient_convection_alpha = 'alpha'
ambient_temperature = 'T_solid'
[]
[]
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)the solid energy conservation equation by the
SolidHeatTransfer
Physics
[Physics]
[NavierStokes]
[SolidHeatTransfer]
[solid]
# On all blocks
block = '${blocks_bed} ${blocks_non_bed}'
initial_temperature = 823.14
thermal_conductivity_solid = 'eff_solid_conductivity'
cp_solid = 'cp_s'
rho_solid = 'rho_s'
# Heat source
external_heat_source = power_density
external_heat_source_blocks = 'flow3'
# Porous flow parameters
ambient_convection_blocks = ${blocks_fluid}
ambient_convection_alpha = 'alpha'
[]
[]
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Auxiliary Variables
Next the AuxVariables are listed which can be used to define fields/variables that are not solved for. They may be used for coupling, for computing material properties, for outputting quantities of interests, and many other uses. In this input file, we define auxiliary variables for items like the Courant-Friedrichs-Lewy (CFL) condition CFL_Now
, density rho_var
, or heat capacity cp_var
. Additionally, we have auxiliary variables that are used in Multi-app Transfers such as the power_density
from the neutronics solve, and rho_var
from the thermal hydraulics solve. Lastly we have auxiliary variables used for heat transfer or friction factor correlations.
[AuxVariables]
[Volume_of_Cell]
order = CONSTANT
family = MONOMIAL
block = ${blocks_fluid}
initial_condition = 0.00012499797344389663
[]
[CFL_Now]
type = MooseVariableFVReal
block = ${blocks_fluid}
[]
[Dt]
type = MooseVariableFVReal
block = ${blocks_fluid}
[]
[porosity_1]
type = MooseVariableFVReal
block = ${blocks_fluid}
[]
[real_vel_x]
type = MooseVariableFVReal
initial_condition = 0
[]
[real_vel_y]
type = MooseVariableFVReal
initial_condition = 0.0
[]
[power_density]
type = MooseVariableFVReal
initial_condition = '${fparse core_power_density}'
block = 'flow3'
[]
[rho_var]
type = MooseVariableFVReal
[]
[cp_var]
type = MooseVariableFVReal
[]
[T_fluid_WD]
type = MooseVariableFVReal
[]
[Wall_Distance]
type = MooseVariableFVReal
[]
[htc_material]
type = MooseVariableFVReal
[]
[Adjusted_HTC_Material]
type = MooseVariableFVReal
[]
[kappa_fluid]
type = MooseVariableFVReal
[]
[Darcy_Value]
type = MooseVariableFVReal
[]
[Forchheimer_Value]
type = MooseVariableFVReal
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Functions
The Functions block is defined next. Here functions are defined that can be used elsewhere in the input file. Most of these function define porosity for specific locations in the model using the ParsedFunction
which is a versatile way of setting up various functions.
[Functions]
[dt_function]
type = ParsedFunction
symbol_values = 'dt'
symbol_names = 'dt'
expression = 'dt'
[]
[porosity_core]
type = ParsedFunction
expression = 0.4011505932
[]
[porosity_cones]
type = ParsedFunction
expression = 0.75
[]
[porosity_plena]
type = ParsedFunction
expression = 0.9999
[]
[porosity_pipe]
type = ParsedFunction
expression = 0.9999
[]
[porosity_diode]
type = ParsedFunction
expression = 0.9999
[]
[Outlet_Average_Pressure_Function]
type = ParsedFunction
symbol_names = 'OAP'
expression = OAP
symbol_values = 'Outlet_Pressure_BC'
[]
[mu_rampdown]
type = ParsedFunction
expression = 1
symbol_names = 'NP'
symbol_values = 'Num_Picards'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Auxiliary Kernels
Similarly we can have Auxiliary Kernels which operate on the Auxiliary Variables. Similarly - the ParsedAux
is a powerful tool in performing various actions that operate on the Auxiliary Variables. Specifically - heat transfer, turbulence, and friction factor correlations can be implemented here.
[AuxKernels]
[volume_Calc]
type = VolumeAux
variable = Volume_of_Cell
block = ${blocks_fluid}
[]
[dt_kernel]
type = FunctionAux
variable = Dt
function = dt_function
[]
[CFL_Calc]
type = ParsedAux
variable = CFL_Now
coupled_variables = 'superficial_vel_x superficial_vel_y Volume_of_Cell Dt'
expression = '(abs(superficial_vel_x) + abs(superficial_vel_y))*Dt/(Volume_of_Cell)^(0.5)'
block = ${blocks_fluid}
[]
[real_vel_x_calc]
type = ParsedAux
variable = real_vel_x
coupled_variables = 'superficial_vel_x porosity_1'
expression = 'superficial_vel_x / porosity_1'
block = ${blocks_fluid}
[]
[real_vel_y_calc]
type = ParsedAux
variable = real_vel_y
coupled_variables = 'superficial_vel_y porosity_1'
expression = 'superficial_vel_y / porosity_1'
block = ${blocks_fluid}
[]
[rho_out]
type = FunctorAux
functor = 'rho'
variable = 'rho_var'
execute_on = 'timestep_begin timestep_end Final'
block = ${blocks_fluid}
[]
[cp_out]
type = FunctorAux
functor = 'cp'
variable = 'cp_var'
execute_on = 'timestep_begin'
block = ${blocks_fluid}
[]
[Whole_Domain_Fluid_Temp]
type = ParsedAux
variable = T_fluid_WD
coupled_variables = 'T_fluid'
expression = 'T_fluid'
block = ${blocks_fluid}
[]
[Whole_Domain_Fluid_Temp_2]
type = ConstantAux
variable = T_fluid_WD
value = 0
block = 'reflector barrel vessel1 vessel2'
[]
[porosity_out]
type = FunctorAux
functor = 'porosity'
variable = 'porosity_1'
block = ${blocks_fluid}
execute_on = 'initial'
[]
[kappa_out]
type = ADFunctorVectorElementalAux
functor = 'kappa'
variable = 'kappa_fluid'
component = '0'
execute_on = 'timestep_end final'
block = ${blocks_fluid}
[]
[Wall_Distance_Aux_Kernel]
type = WallDistanceMixingLengthAux
variable = Wall_Distance
von_karman_const = 1
von_karman_const_0 = 1
walls = 'wall1'
[]
[Adjust_HTC]
type = ParsedAux
variable = Adjusted_HTC_Material
coupled_variables = 'htc_material Wall_Distance'
expression = 'htc_material*Wall_Distance'
block = ${blocks_fluid}
[]
[d_var_aux]
type = ADFunctorVectorElementalAux
variable = Darcy_Value
functor = combined_linear
block = ${blocks_fluid}
component = '0'
[]
[f_var_aux]
type = ADFunctorVectorElementalAux
variable = Forchheimer_Value
functor = combined_quadratic
block = ${blocks_fluid}
component = '0'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Fluid Properties
Very briefly we introduce the Fluid Properties which imports thermophysical properties at evaluates this data at the temperature and pressure that is calculated by the thermal hydraulic solution. Here FLiBe molten salt thermophysical properties are loaded in.
[FluidProperties]
[fluid_properties]
type = FlibeFluidProperties
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Functor Materials
Next we define Functor Materials which define specific materials which are functors and can be used and incorporated within the Kernels
or Auxiliary Kernels
to perform specific calculations.
A few examples here are the GeneralFunctorFluidProps
which performs the evaluation of thermophysical properties of the FliBe salt from the FluidProperties
and the thermal hydraulic variables that are being solved for (i.e., T_fluid, pressure, speed). Additionally, the characteristic length or the hydraulic diameter, porosity, and friction factors of flow regions in the model can also be defined here and used in the Action or FVKernels.
[FunctorMaterials]
[GFFP]
type = GeneralFunctorFluidProps
T_fluid = 'T_fluid'
characteristic_length = characteristic_length
fp = fluid_properties
porosity = 'porosity'
pressure = 'pressure'
speed = speed
mu_rampdown = 'mu_rampdown'
block = ${blocks_fluid}
[]
## Characteristic length
[characteristic_length]
type = PiecewiseByBlockFunctorMaterial
prop_name = characteristic_length
block = ${blocks_fluid}
subdomain_to_prop_value = '1 ${D_H_downcomer}
2 ${D_H_flow2}
3 ${pebble_diameter}
4 ${pebble_diameter}
5 ${D_H_flow5}
6 ${D_H_diode}
7 ${D_H_diode}
8 ${D_H_diode}
9 ${pebble_diameter}
20 ${D_H_downcomer}
21 ${D_H_outlet}'
[]
## Porosity
[porosity_energy]
type = ADPiecewiseByBlockFunctorMaterial
prop_name = porosity_energy
subdomain_to_prop_value = '1 ${porosity_free_flow}
2 ${porosity_free_flow}
3 ${porosity_bed}
4 ${porosity_cone}
5 ${porosity_free_flow}
6 ${porosity_free_flow}
7 ${porosity_free_flow}
8 ${porosity_free_flow}
9 ${porosity_cone}
20 ${porosity_free_flow}
21 ${porosity_free_flow}
10 ${porosity_solid}
12 ${porosity_solid}
13 ${porosity_solid}
14 ${porosity_solid}'
[]
[porosity]
type = ADPiecewiseByBlockFunctorMaterial
prop_name = porosity
subdomain_to_prop_value = '1 ${porosity_free_flow}
2 ${porosity_free_flow}
3 ${porosity_bed}
4 ${porosity_cone}
5 ${porosity_free_flow}
6 ${porosity_free_flow}
7 ${porosity_free_flow}
8 ${porosity_free_flow}
9 ${porosity_cone}
20 ${porosity_free_flow}
21 ${porosity_free_flow}
10 ${porosity_solid}
12 ${porosity_solid}
13 ${porosity_solid}
14 ${porosity_solid}'
[]
[diode]
type = NSFVFrictionFlowDiodeFunctorMaterial
direction = '-1 0 0'
additional_linear_resistance = '1000 0 0'
additional_quadratic_resistance = '100 0 0'
base_linear_friction_coefs = 'Darcy_coefficient'
base_quadratic_friction_coefs = 'Forchheimer_coefficient'
sum_linear_friction_name = 'diode_linear'
sum_quadratic_friction_name = 'diode_quad'
block = '6 7 8'
turn_on_diode = true
[]
[combine_linear_friction]
type = ADPiecewiseByBlockVectorFunctorMaterial
prop_name = 'combined_linear'
subdomain_to_prop_value = '1 Darcy_coefficient
2 Darcy_coefficient
3 Darcy_coefficient
4 Darcy_coefficient
5 Darcy_coefficient
6 diode_linear
7 diode_linear
8 diode_linear
9 Darcy_coefficient
20 Darcy_coefficient
21 Darcy_coefficient'
[]
[combine_quadratic_friction]
type = ADPiecewiseByBlockVectorFunctorMaterial
prop_name = 'combined_quadratic'
subdomain_to_prop_value = '1 Forchheimer_coefficient
2 Forchheimer_coefficient
3 Forchheimer_coefficient
4 Forchheimer_coefficient
5 Forchheimer_coefficient
6 diode_linear
7 diode_linear
8 diode_linear
9 Forchheimer_coefficient
20 Forchheimer_coefficient
21 Forchheimer_coefficient'
[]
## Thermal conductivity of the fluid
[pebble_bed_fluid_effective_conductivity]
type = ${pebble_bed_fluid_effective_conductivity_type}
block = ${blocks_bed}
porosity = porosity_energy
[]
[non_pebble_bed_kappa]
type = ADGenericVectorFunctorMaterial
prop_names = 'kappa'
prop_values = 'k k k'
block = ${blocks_non_bed}
[]
## Drag coefficients
[pebble_bed_drag_coefficient]
type = FunctorKTADragCoefficients
T_solid = T_solid
T_fluid = T_fluid
porosity = porosity
block = ${blocks_bed}
[]
[churchill_drag_coefficient]
type = FunctorChurchillDragCoefficients
block = 'flow1 inlet dio1 dio2 dio3'
[]
[drag_open_flow_regions]
type = FunctorIsotropicFunctorDragCoefficients
Darcy_coefficient_sub = 0
Forchheimer_coefficient_sub = ${Forch_open}
block = 'flow2 flow5 outlet'
[]
## Heat transfer coefficients
[pebble_bed_alpha]
type = FunctorPetrovicPebbleBedHTC
block = ${blocks_bed}
porosity = porosity_energy
[]
[equivalent_alpha_flow1]
type = FunctorDittusBoelterWallHTC
C = '${fparse C_DB * ApV_flow_1}'
block = flow1
[]
[equivalent_alpha_diodes]
type = FunctorDittusBoelterWallHTC
C = '${fparse C_DB * ApV_diode}'
block = 'dio1 dio2 dio3'
[]
[convert_wall_htc_to_alpha]
type = ADGenericFunctorMaterial
prop_names = 'alpha'
prop_values = 'wall_htc'
block = 'dio1 dio2 dio3 flow1'
[]
# in some regions we do not care about volumetric
# heat transfer, but we might have to do sanity checks here
[alpha_null]
type = ADGenericFunctorMaterial
prop_names = 'alpha'
prop_values = '0'
block = 'flow2 flow5 outlet inlet'
[]
## Solid phase properties
[pebble_bed_kappa_s]
type = FunctorPebbleBedKappaSolid
radiation = BreitbachBarthels
solid_conduction = ChanTien
fluid_conduction = ZBS
emissivity = ${pebble_emissivity}
Youngs_modulus = 9e9
Poisson_ratio = 0.136
wall_distance = bed_geometry
T_solid = T_solid
block = ${blocks_bed}
porosity = porosity_energy
[]
[pebble_bed_solid_properties]
type = PronghornSolidFunctorMaterialPT
solid = graphite
T_solid = T_solid
block = ${blocks_bed}
[]
[steel]
type = ADGenericFunctorMaterial
block = 'barrel vessel1 vessel2'
prop_names = 'rho_s cp_s k_s'
prop_values = '8000.0 ${fparse 500.0} 21.5'
[]
[reflector_full_density_graphite]
type = ADGenericFunctorMaterial
block = 'reflector'
prop_names = 'rho_s cp_s k_s'
prop_values = '1740.0 ${fparse 1697.0} 26.0'
[]
[time_derivatives_constants]
type = ADGenericFunctorMaterial
prop_names = 'drho_s_dt'
prop_values = '0'
block = '${blocks_bed}'
[]
# Modeling solid everywhere. Open flow regions are modeled
# as very low density/conductivity regions. Heat transfer
# through them will be facilitated by conjugate heat transfer
# from the adjacent walls that is converted to a volumetric term
[dummy_open_flow_region_solid_props]
type = ADGenericFunctorMaterial
prop_names = 'rho_s cp_s k_s'
prop_values = '1 1 1e-4'
block = '${blocks_free_flow}'
[]
# write k_s into kappa_s so we can use the same
# kernel everywhere
[non_pebble_bed_eff_solid_conductivity]
type = ADGenericVectorFunctorMaterial
prop_names = 'eff_solid_conductivity'
prop_values = 'k_s k_s k_s'
block = '${blocks_free_flow} reflector barrel vessel1 vessel2'
[]
[pebble_bed_eff_solid_conductivity]
type = ADGenericVectorFunctorMaterial
prop_names = 'eff_solid_conductivity'
prop_values = 'kappa_s kappa_s kappa_s'
block = '${blocks_bed}'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Postprocessors
Nearing the end of the model, the Postprocessors block specifies calculations that should be made regarding the solution that may be used during picard iterations or for data analysis after convergence. There are many different types used in this model including ElementExtremeValue
, ParsedPostprocessor
which also gives the user a wide berth of possibilities to calculate specific values of interest, ElementIntegralVariablePostprocessor
, and SideAverageValue
to name a few. Here both postprocessors for the thermal-hydraulic solve are listed which operate on the pressure, velocity, and temperatures solved for in the numerical simulation, as well as values that were transferred in from Griffin like the power_density
.
[Postprocessors]
[dt]
type = TimestepSize
[]
[Max_CFL]
type = ElementExtremeValue
variable = CFL_Now
block = ${blocks_fluid}
[]
[New_Dt]
type = ParsedPostprocessor
pp_names = 'Max_CFL dt'
#Relaxed and limited growth timestep so that we dont end up in a cyclical problem
expression = 'min((10000*t/Max_CFL * dt/2 + dt/2) , dt*2)'
execute_on = 'timestep_end'
use_t = true
[]
[Num_Picards]
type = Receiver
default = 0
[]
[Inlet_Temperature_BC]
type = Receiver
default = 823.15
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[Outlet_Pressure_BC]
type = Receiver
default = 2e5
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[Outlet_Velocity_y]
type = SideAverageValue
boundary = 'outlet'
variable = superficial_vel_y
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
### Griffin values
[total_power]
type = ElementIntegralVariablePostprocessor
block = 'flow3'
variable = power_density
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
### Pronghorn Values ###
[Outlet_Velocity_PH]
type = ParsedPostprocessor
expression = 'mass_flow_out / area_SAM / density'
pp_names = 'mass_flow_out'
constant_names = 'area_SAM density'
constant_expressions = '1.327511 2201'
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[Outlet_Pressure_PH]
type = SideAverageValue
boundary = 'outlet'
variable = pressure
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[Outlet_Temperature_PH]
type = SideAverageValue
boundary = 'outlet'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[Heatflux_RCCS]
type = SideIntegralVariablePostprocessor
boundary = 'RCSS'
variable = T_solid
[]
[Tfluid_core]
type = ElementAverageValue
block = 'flow3'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Tfluid_bottom]
type = ElementAverageValue
block = 'flow2'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Tfluid_upper]
type = ElementAverageValue
block = 'flow4 flow5'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Tfluid_diode]
type = ElementAverageValue
block = 'dio1 dio2 dio3'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Tfluid_downcomer]
type = ElementAverageValue
block = 'flow1'
variable = T_fluid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Reflector_Temp]
type = ElementAverageValue
block = 'reflector'
variable = T_solid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Barrel_Temp]
type = ElementAverageValue
block = 'barrel'
variable = T_solid
execute_on = 'INITIAL TIMESTEP_END'
[]
[Vessel_Temp]
type = ElementAverageValue
block = 'vessel1 vessel2'
variable = T_solid
execute_on = 'INITIAL TIMESTEP_END'
[]
### ###
[inlet_mdot]
type = Receiver
default = 1173.0
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[inlet_area]
type = AreaPostprocessor
boundary = 'inlet'
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[mass_flow_out]
type = VolumetricFlowRate
boundary = 'outlet'
advected_quantity = 'rho_var'
vel_x = superficial_vel_x
vel_y = superficial_vel_y
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[mass_flow_in]
type = VolumetricFlowRate
boundary = 'inlet'
advected_quantity = 'rho_var'
vel_x = superficial_vel_x
vel_y = superficial_vel_y
execute_on = 'INITIAL TIMESTEP_END TRANSFER'
[]
[mass_flow_1]
type = VolumetricFlowRate
boundary = 'MF_1'
advected_quantity = 'rho_var'
vel_x = superficial_vel_x
vel_y = superficial_vel_y
execute_on = 'TIMESTEP_END TRANSFER'
[]
[mass_flow_2]
type = VolumetricFlowRate
boundary = 'MF_2'
advected_quantity = 'rho_var'
vel_x = superficial_vel_x
vel_y = superficial_vel_y
execute_on = 'TIMESTEP_END TRANSFER'
[]
[mass_flow_3]
type = VolumetricFlowRate
boundary = 'MF_3'
advected_quantity = 'rho_var'
vel_x = superficial_vel_x
vel_y = superficial_vel_y
execute_on = 'TIMESTEP_END TRANSFER'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Preconditioning
Next we declare the Preconditioning block which specifies what kind of preconditioning matrix the user wants to implement. Here the Single Matrix Preconditioner (SMP) is used with specific PETSc options selected.
[Preconditioning]
[SMP]
type = SMP
full = true
petsc_options_iname = ' -pc_type -pc_factor_mat_solver_type
-ksp_gmres_restart -pc_factor_shift_type'
petsc_options_value = ' lu superlu_dist 50 NONZERO'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Executioner - Solving the Equations
The Executioner block defines how the non-linear system will be solved. Since this is a transient problem, we are using a Transient executioner. Pronghorn makes use of automatic differentiation, more information here, to compute an exact Jacobian, so we make use of the Newton method to solve the non-linear system.
We then specify the solver tolerances. These may be loosened to obtain a faster solve. They should initially be set fairly small to obtain a tight convergence, then relaxed to improve performance.
Finally we set the time parameters for the simulation. We choose a very large runtime. We use an adaptive time-stepper to increase the time step over the course of the simulation which uses a postprocessor to define what the new time step should be. Because we are using an implicit scheme, we can take very large time steps and still have a stable simulation.
[Executioner]
type = Transient # Pseudo transient to reach steady state.
solve_type = 'NEWTON'
petsc_options = '-snes_converged_reason'
line_search = 'none'
# Problem time parameters.
end_time = 1e+6
dtmin = 1e-6
dtmax = 10000
# Iterations parameters.
l_max_its = 50
l_tol = 1e-6
nl_max_its = 25
nl_rel_tol = 1e-10
nl_abs_tol = 1e-11
nl_forced_its = 1
# Steady state detection.
steady_state_detection = true
steady_state_tolerance = 1e-12
steady_state_start_time = 0
auto_advance = true
# Adaptive time step scheme.
[TimeStepper]
type = PostprocessorDT
dt = 1e-1
postprocessor = New_Dt
[]
# Automatic scaling
automatic_scaling = true
off_diagonals_in_auto_scaling = true
compute_scaling_once = false
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)Outputs
Lastly we define the output forms for the model which will be filled with the information listed in the Postprocessor
block and the Variables
and Auxiliary Variables
blocks.
We then define an Exodus output. This will have the multi-dimensional distributions of the quantities Pronghorn solved for: the fluid velocities, the pressure and the temperature fields. We also include the material properties to help us understand the behavior of the core.
We also define a CSV output which will list all of the postprocessors for each time step.
[Outputs]
print_linear_converged_reason = false
print_linear_residuals = false
print_nonlinear_converged_reason = false
perf_graph = true
csv = true
execute_on = 'INITIAL FINAL'
[console]
type = Console
outlier_variable_norms = false
all_variable_norms = false
[]
[exo]
type = Exodus
execute_on = 'FINAL'
[]
[]
(pbfhr/gFHR/steady/gFHR_pronghorn_ss.i)References
- Javier Ortensi, Cole M. Mueller, Stefano Terlizzi, Guillaume Giudicelli, and Sebastian Schunert.
Fluoride-cooled high-temperature pebble-bed reactor reference plant model.
Technical Report INL/RPT-23-72727, Idaho National Laboratory, 2023.[BibTeX]