GCMR Core Thermal Model

Point of Contact: Lise Charlot (lise.charlot.at.inl.gov)

Model link: GCMR Core Thermal Model

Mesh file

A 3-D mesh for the core is generated using the MOOSE Reactor module. Details of the mesh for an assembly is shown in Figure 1.

Figure 1: Details of the core 3D mesh

First, the pincell for the moderator, fuel and coolant channels are created. Several rings are used for the fuel channels to be able to prescribe a non-uniform power density in the assembly.

  [moderator_pincell]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6 # must be six to use hex pattern
    num_sectors_per_side = '2 2 2 2 2 2 '
    background_intervals = 2.
    background_block_ids = '1'
    polygon_size = ${pincell_apothem}
    polygon_size_style = 'apothem'
    ring_radii = '${fparse pincell_apothem / 2 }'
    ring_intervals = '2'
    ring_block_ids = '103 101' # 103 is tri mesh
    preserve_volumes = on
    quad_center_elements = false
  []
  [coolant_pincell]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6 # must be six to use hex pattern
    num_sectors_per_side = '2 2 2 2 2 2 '
    background_intervals = 2.
    background_block_ids = '2'
    polygon_size = ${pincell_apothem}
    polygon_size_style = 'apothem'
    ring_radii = '${radius_coolant}'
    ring_intervals = '2'
    ring_block_ids = '203 201' # 203 is tri mesh
    preserve_volumes = on
    quad_center_elements = false
  []
  [fuel_pincell_ring1]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6 # must be six to use hex pattern
    num_sectors_per_side = '2 2 2 2 2 2 '
    background_intervals = 2.
    background_block_ids = '3'
    polygon_size = ${pincell_apothem}
    polygon_size_style = 'apothem'
    ring_radii = '${radius_fuel}'
    ring_intervals = '3'
    ring_block_ids = '303 301' # 303 is tri mesh
    preserve_volumes = on
    quad_center_elements = false
  []
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

Using multiple pincells, the assembly pattern is created using the PatternedHexMeshGenerator. The outermost duct block represents the bypass and will be deleted.

[Mesh]
  [fuel_assembly]
    type = PatternedHexMeshGenerator
    inputs = 'coolant_pincell fuel_pincell_ring1 fuel_pincell_ring2 fuel_pincell_ring3 fuel_pincell_ring4 moderator_pincell'
    # Pattern ID     0                 1                  2                  3                  4                   5
    hexagon_size = ${assembly_apothem}
    background_block_id = 10
    background_intervals = 2
    duct_block_ids = '12 11'
    duct_sizes_style = apothem
    duct_sizes = '${fparse assembly_apothem - 0.0008} ${fparse assembly_apothem - 0.0005}'
    duct_intervals = '3 1'
    pattern = '4 4 0 4 4;
              4 0 3 3 0 4;
             0 3 2 0 2 3 0;
            4 3 0 1 1 0 3 4;
           4 0 2 1 5 1 2 0 4;
            4 3 0 1 1 0 3 4;
             0 3 2 0 2 3 0;
              4 0 3 3 0 4;
               4 4 0 4 4'
  []
[]
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

The assembly mesh is then used to create the core layout.

[Mesh]
  [core]
    type = PatternedHexMeshGenerator
    inputs = 'fuel_assembly'
    pattern_boundary = none
    generate_core_metadata = true
    pattern = '0 0 0 0 0;
              0 0 0 0 0 0;
             0 0 0 0 0 0 0;
            0 0 0 0 0 0 0 0;
           0 0 0 0 0 0 0 0 0;
            0 0 0 0 0 0 0 0;
             0 0 0 0 0 0 0;
              0 0 0 0 0 0;
               0 0 0 0 0'
  []
[]
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

The reflector is added using the PeripheralRingMeshGenerator mesh generator.

[Mesh]
  [reflector]
    type = PeripheralRingMeshGenerator
    input = core
    peripheral_layer_num = 2
    peripheral_ring_radius = 0.9
    input_mesh_external_boundary = 10000
    peripheral_ring_block_id = 250
    peripheral_ring_block_name = reflector
  []
[]
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

This 2-D mesh is then extruded to create the 3D mesh.

[Mesh]
  [extrude]
    type = AdvancedExtruderGenerator
    input = reflector
    heights = '2'
    num_layers = '10'

    direction = '0 0 1'
    top_boundary = 2000
    bottom_boundary = 3000
  []
[]
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

A sideset for the coolant boundary is created and the coolant channels removed.

  [add_coolant_boundary]
    type = SideSetsBetweenSubdomainsGenerator
    input = extrude
    primary_block = '2'
    paired_block = '201'
    new_boundary = coolant_boundary
  []

  [fuel_assembly_final]
    type = BlockDeletionGenerator
    block = '201 203'
    input = add_coolant_boundary
  []
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

A sideset for the bypass boundary is created and the bypass block is removed.

  [add_bypass_boundary]
    type = SideSetsBetweenSubdomainsGenerator
    input = fuel_assembly_final
    primary_block = '12'
    paired_block = '11'
    new_boundary = bypass_boundary
  []
  [add_bypass_boundary_out]
    type = SideSetsBetweenSubdomainsGenerator
    input = add_bypass_boundary
    primary_block = '250'
    paired_block = '11'
    new_boundary = bypass_boundary
  []
  [remove_bypass]
    type = BlockDeletionGenerator
    block = '11'
    input = add_bypass_boundary_out
  []
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

The mesh is then rotated to match the subchannel mesh orientation.

[Mesh]
  [rotate]
    type = TransformGenerator
    input = remove_bypass
    transform = ROTATE
    vector_value = '0 0 90'
  []
[]
(microreactors/gcmr/bypass_flow/mesh_bypass.i)

This mesh is used for the heat conduction problem. The coolant channels and the bypass flow have their own meshes generated internally.

Heat Conduction Model

The heat conduction input file solves for the temperature in the fuel channels, moderator and reflector. The material properties for each block are defined depending on their composition using the HeatConductionMaterial and Density material blocks.

A spatially variable power density is imposed in the fuel rods. This is done using several functions and assigning them to the power_density AuxVariable. The heat source is then applied using a CoupledForce kernel.

[Kernels]
  [heat_source_fuel]
    type = CoupledForce
    variable = T
    block = '301 303 401 403 501 503 601 603'
    v = power_density
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

The coupling to the helium flow in the cooling channels and in the bypass between the assemblies is performed through convective boundary conditions. AuxVariables for the heat transfer coefficient and bulk temperatures in the coolant channels and in the bypass are created and used in the boundary condition blocks. The value of these variables will be assigned by the Transfers system.

  [cooling_channels]
    type = CoupledConvectiveHeatFluxBC
    boundary = coolant_boundary
    T_infinity = T_fluid
    htc = htc
    variable = T
  []
  [bypass_conv]
    type = CoupledConvectiveHeatFluxBC
    boundary = bypass_boundary
    T_infinity = T_bypass
    htc = htc_bypass
    variable = T
  []
(microreactors/gcmr/bypass_flow/core.i)

In addition, a convective boundary condition is assigned to the outer surface to model the heat losses through the vessel.

[BCs]
  [outer_to_env]
    type = CoupledConvectiveHeatFluxBC
    boundary = 10000
    T_infinity = 800
    htc = 10
    variable = T
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

Bypass flow Model

The bypass flow is modeled using Pronghorn-SC. It includes a specific problem for inter-assembly subchannels in an hexagonal pattern.

warningwarning

The tri-inter wrapper model has not been validated for gases. This model has been developed is for capability demonstration purposes only.

The mesh is defined using the TriInterWrapperMesh with parameters consistent with the 3D mesh used for the heat conduction problem.

[TriInterWrapperMesh]
  [sub_channel]
    type = TriInterWrapperMeshGenerator
    nrings = ${n_rings}
    n_cells = 50
    flat_to_flat = '${fparse 2 * assembly_apothem - 0.001}'
    heated_length = 2.0
    assembly_pitch = '${fparse 2 * assembly_apothem}'
    side_bypass = 0.001
    tight_side_bypass = true
  []
[]
(microreactors/gcmr/bypass_flow/bypass.i)

The helium fluid properties are defined using an ideal gas with the following parameters:

[FluidProperties]
  [helium]
    type = IdealGasFluidProperties
    molar_mass = 4e-3
    gamma = 1.67
    k = ${k}
    mu = ${mu}
  []
[]
(microreactors/gcmr/bypass_flow/bypass.i)

The flow area and wet perimeter of the subchannels are defined as AuxVariables. They are initialized using the TriInterWrapperFlowAreaIC and TriInterWrapperWettedPerimIC objects to be consistent with the mesh.

The heat transferred from the moderator block is applied using the linear heat rate AuxVariable q_prime. It is defined using a ParsedAux AuxKernel using the wet perimeter (which is equal to the heated perimeter in this case), and the flux transferred from the heat conduction problem. The value of the linear heat rate is bounded to improve the convergence of the fixed point algorithm.

[AuxKernels]
  [q_prime_aux]
    type = ParsedAux
    coupled_variables = 'w_perim flux'
    variable = q_prime
    expression = 'min(max(-10000, w_perim*flux), 30000)'
    execute_on = 'INITIAL TIMESTEP_BEGIN'
  []
[]
(microreactors/gcmr/bypass_flow/bypass.i)

The heat transfer coefficient to be transferred to the heat conduction problem is calculated using ParsedAux AuxKernel. It is set here to a constant value, but a more complex correlation such as Dittus-Boelter could be implemented. This approach was not chosen for this case because it was significantly increasing the number of the fixed point iterations of the multiphysics coupling.

The solver and flow model are set using the LiquidMetalInterWrapper1PhaseProblem.

[SubChannel]
  type = TriInterWrapper1PhaseProblem
  fp = helium
  n_blocks = 1
  beta = 0.1
  P_out = ${P_out}
  CT = 1.0
  compute_density = true
  compute_viscosity = true
  compute_power = true
  P_tol = 1.0e-6
  T_tol = 1.0e-6
  implicit = false
  segregated = true
  staggered_pressure = true
  T_maxit = 20
  monolithic_thermal = false
[]
(microreactors/gcmr/bypass_flow/bypass.i)

Note that P_out is set to the outlet pressure and the AuxVariable P is initialized to zero as P is the pressure difference with the outlet pressure. The value P+P_out is used to calculate the fluid properties.

Thermal-hydraulic model of the coolant channels

The MOOSE thermal-hydraulics module (THM) is used to mode the response of the coolant channels. The input file represents a single channel that will be replicated and translated through the MultiApp system.

The helium fluid properties are defined using an ideal gas with the following parameters:

[FluidProperties]
  [helium]
    type = IdealGasFluidProperties
    molar_mass = 4e-3
    gamma = 1.67
    k = 0.2556
    mu = 3.22639e-5
  []
[]
(microreactors/gcmr/bypass_flow/cooling_channel.i)

The friction factor and heat transfer coefficient are defined using the default correlations of the Closures1PhaseTHM closures sets which are the Churchill equation for the friction factor and the Dittus Boelter correlation for the heat transfer coefficient.

[Closures]
  [thm]
    type = Closures1PhaseTHM
  []
[]
(microreactors/gcmr/bypass_flow/cooling_channel.i)

The channel is defined using a FlowChannel1Phase component and the geometry parameters of a single coolant channel.

The fluid temperature and velocity are prescribed at the channel inlet using a InletVelocityTemperature1Phase component. The outlet pressure is prescribed using a Outlet1Phase component.

A convective boundary condition is applied on the channel wall using aHeatTransferFromExternalAppTemperature1Phase component. It will use the T_wall AuxVariable, the fluid bulk temperature, and the heat transfer coefficient generated by the closure set to compute the heat transferred to the channel. The value of T_wall will be transferred from the 3D heat conduction problem in the core.

[Components]
  [inlet]
    type = InletVelocityTemperature1Phase
    vel = 15
    T = ${T_in}
    input = channel:in
  []
  [channel]
    type = FlowChannel1Phase
    position = '0 0 0'
    orientation = '0 0 1'
    length = ${length_channel}
    A = ${A_channel}
    n_elems = ${channel_n_elems}
    D_h = '${fparse 2 * radius_coolant}'
  []
  [outlet]
    type = Outlet1Phase
    p = ${p_out}
    input = channel:out
  []
  [ht]
    type = HeatTransferFromExternalAppTemperature1Phase
    flow_channel = channel
    P_hf = ${P_hf_channel}
    initial_T_wall = 1200
  []
[]
(microreactors/gcmr/bypass_flow/cooling_channel.i)

The Steady Executioner is used. The initial guess for the velocity is defined as the inlet velocity, the pressure initial guess is the outlet pressure, and the temperature is set to a linear function ranging from the prescribed inlet temperature to the arbitrary value of 1100 K.

Multiphysics Coupling

The heat conduction simulation is the parent app. The cooling channels and bypass flow are sub apps.

[MultiApps]
  [bypass_flow]
    type = FullSolveMultiApp
    positions = '0 0 0'
    input_files = bypass.i
    max_procs_per_app = 1
    execute_on = ' TIMESTEP_END'
    bounding_box_padding = '0.01 0.01 0.01'
    ignore_solve_not_converge = true
    keep_solution_during_restore = true
  []
  [channel_flow]
    type = FullSolveMultiApp
    positions_file = 'channel_centers.txt'
    input_files = cooling_channel.i
    max_procs_per_app = 1
    execute_on = 'TIMESTEP_END'
    bounding_box_padding = '0.1 0.1 0.1'
    output_in_position = true
    keep_solution_during_restore = true
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

The variables transfers are shown in Figure 2.

Figure 2: MultiApp and transfers

The wall temperature needed for the flow in the cooling channels is calculated using a NearestPointLayeredSideAverage UserObject in the heat conduction input file.

[UserObjects]
  [T_wall_coolant_uo]
    type = NearestPointLayeredSideAverage
    variable = T
    boundary = coolant_boundary
    direction = z
    num_layers = 51
    points_file = channel_centers.txt
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

It is then transferred using a MultiAppGeneralFieldUserObjectTransfer.

[Transfers]
  [T_wall_to_coolant]
    type = MultiAppGeneralFieldUserObjectTransfer
    source_user_object = T_wall_coolant_uo
    variable = T_wall
    to_multi_app = channel_flow
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

The heat flux for the bypass flow is calculated using the bypass wall temperature. The wall temperature is calculated with a NearestPointLayeredSideAverage UserObject and assigned to the T_wall_bypass AuxVariable using a SpatialUserObjectAux AuxKernel. The heat flux is then calculated using a ParsedAux AuxKernel.

[UserObjects]
  [T_wall_bypass_uo]
    type = NearestPointLayeredSideAverage
    variable = T
    boundary = bypass_boundary
    direction = z
    num_layers = 51
    points_file = bypass_positions.txt
  []
[]
(microreactors/gcmr/bypass_flow/core.i)
[AuxKernels]
  [T_wall_bypass_aux]
    type = SpatialUserObjectAux
    user_object = T_wall_bypass_uo
    variable = T_wall_bypass
  []
[]
(microreactors/gcmr/bypass_flow/core.i)
[AuxKernels]
  [flux_aux]
    type = ParsedAux
    coupled_variables = 'T_bypass T_wall_bypass htc_bypass'
    variable = flux_bypass
    expression = 'htc_bypass * (T_wall_bypass - T_bypass)'
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

The heat flux is then transferred to the bypass flow sub-app using a MultiAppGeometricInterpolationTransfer transfer.

[Transfers]
  [flux_to_bypass]
    type = MultiAppGeometricInterpolationTransfer
    source_variable = flux_bypass
    variable = flux
    to_multi_app = bypass_flow
  []
[]
(microreactors/gcmr/bypass_flow/core.i)

Finally, the bulk coolant temperatures and heat transfer coefficient are transferred form the sub-apps using MultiAppGeneralFieldNearestLocationTransfer transfers.

[Transfers]
  [T_wall_to_coolant]
    type = MultiAppGeneralFieldUserObjectTransfer
    source_user_object = T_wall_coolant_uo
    variable = T_wall
    to_multi_app = channel_flow
  []
  [T_coolant]
    type = MultiAppGeneralFieldNearestLocationTransfer
    from_multi_app = channel_flow
    source_variable = T
    variable = T_fluid
  []
  [htc_coolant]
    type = MultiAppGeneralFieldNearestLocationTransfer
    from_multi_app = channel_flow
    source_variable = htc
    variable = htc
  []

  [flux_to_bypass]
    type = MultiAppGeometricInterpolationTransfer
    source_variable = flux_bypass
    variable = flux
    to_multi_app = bypass_flow
  []
  [T_bypass]
    type = MultiAppGeneralFieldNearestLocationTransfer
    from_multi_app = bypass_flow
    source_variable = T
    variable = T_bypass
  []
  [htc_bypass]
    type = MultiAppGeneralFieldNearestLocationTransfer
    from_multi_app = bypass_flow
    source_variable = htc
    variable = htc_bypass
  []
  [SumWij]
    type = MultiAppGeneralFieldNearestLocationTransfer
    from_multi_app = bypass_flow
    source_variable = SumWij
    variable = SumWij
  []
[]
(microreactors/gcmr/bypass_flow/core.i)