2D Generic Heat Pipe Microreactor (gHPMR) Model Mesh

warningwarning

This meshing script generates a mesh in a coarse form. Convergence studies for the physics of interest should be performed by the user.

The 2D generic Heat Pipe Microreactor (gHPMR) Model Mesh is created in several steps:

  1. The fuel pin cell and heat pipe pin cell meshes are generated.

  2. The fuel assembly meshes are created.

  3. The core mesh is generated from the lattice of assembly meshes.

  4. The control drum meshes are generated and translated to account for each drum position and placement in the core.

  5. The reflector mesh is generated.

  6. The final 2D core mesh is generated including outer reactor vessel boundary.

A more detailed explanation of each step follows below.

Fuel Pin Cell Meshes

First, there are 5 fuel pin meshes that are generated - 4 are for assemblies without a control rod channel and 1 for an assembly with a control rod channel.

  [fuel_pin_R0]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${fuel_pin_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${fuel_R0_tri_block_id}'
    ring_block_names = '${fuel_R0_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
  [fuel_pin_R1]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${fuel_pin_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${fuel_R1_tri_block_id}'
    ring_block_names = '${fuel_R1_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
  [fuel_pin_R2]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${fuel_pin_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${fuel_R2_tri_block_id}'
    ring_block_names = '${fuel_R2_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
  [fuel_pin_R3]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${fuel_pin_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${fuel_R3_tri_block_id}'
    ring_block_names = '${fuel_R3_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
  [fuel3_pin]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${fuel_pin_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${fuel3_tri_block_id}'
    ring_block_names = '${fuel3_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
  # Call it a pin so we know it is a pin cell
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 1: The five 2D fuel pin cell meshes; the yellow pin mesh is the pin used in the fuel assembly which contains a control rod channel.

Then a pin cell mesh is generated for the heat pipe.

[Mesh]
  [heat_pipe_pin]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    ring_radii = '${heat_pipe_radius}'
    ring_intervals = '${num_cell_ring_intervals}'
    ring_block_ids = '${heat_pipe_tri_block_id}'
    ring_block_names = '${heat_pipe_tri_block_name}'
    background_intervals = 1
    background_block_ids = '${monolith_quad_block_id}'
    background_block_names = '${monolith_quad_block_name}'
    preserve_volumes = on
  []
[]
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 2: The 2D heat pipe pin cell mesh.

Two fake pin cell meshes are generated for the purpose of deletion in future steps.

  [fake_pin]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = '6'
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    background_block_ids = '${to_remove_tri_block_id}'
    background_block_names = '${to_remove_tri_block_name}'
  []
  # We also delete this one, but delete it separately so we can generate a cohesive boundary for meshing
  [fake_pin_2]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = '6'
    flat_side_up = false
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    polygon_size = '${cell_apothem}'
    background_block_ids = '${to_remove2_tri_block_id}'
    background_block_names = '${to_remove2_tri_block_name}'
  []
  #
  # Assembly type 1 R0
  #
(microreactors/gHPMR/2D_gHPMR_Final.i)

Fuel Assembly

Fuel Pin assemblies are then generated for each of the 5 fuel pin meshes.

The fuel pin cell assembly is generated using the previous step's pin cell meshes. The fake pin cells are then deleted from the assembly mesh in order to create a void for the heat pipe meshes in future steps. The outer assembly boundary is generated. Boundary ids are renamed and meta data is added back to the assembly mesh. This process is repeated for the four other fuel assemblies.

commentnote:Metadata

When the hexagonal meshes are modified, they lose the original metadata. Thus reapplying the metadata from before the modifications is necessary to generate the assemblies. This will no longer be necessary in future versions.

  [assembly1_R0]
    type = PatternedHexMeshGenerator
    inputs = 'fake_pin fuel_pin_R0 heat_pipe_pin'
    rotate_angle = 0
    pattern_boundary = none
    pattern = '   0 1 1 0;
                 1 1 2 1 1;
                1 2 1 1 2 1;
               0 1 1 2 1 1 0;
                1 2 1 1 2 1;
                 1 1 2 1 1;
                  0 1 1 0'
    id_name = 'pin_id'
  []
  # delete fake cell
  [assembly1_R0_del]
    type = BlockDeletionGenerator
    input = assembly1_R0
    block = '${to_remove_tri_block_id}'
    #new_boundary = 'inner_bdy'
  []
  [assembly1_R0_outer_hex]
    type = HexagonConcentricCircleAdaptiveBoundaryMeshGenerator
    hexagon_size_style = apothem
    hexagon_size = '${asm_apothem}'
    # Re-use pin_cell_sectors_per_side, the number of sectors will be overridden by automatic refinement by the subsequent XYDG
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    background_block_ids = '${monolith_tri_block_id}'
    background_block_names = '${monolith_tri_block_name}'
  []
  # add background meshes of hex assembly and merge with hex cells
  [hex_assembly1_R0]
    type = XYDelaunayGenerator
    boundary = 'assembly1_R0_outer_hex'
    holes = 'assembly1_R0_del'
    stitch_holes = 'true'
    refine_holes = 'false'
    add_nodes_per_boundary_segment = ${hex_assembly_xydg_nodes_to_add}
    output_boundary = 10000
    # Get a bunch of errors if this is set to 'true'
    refine_boundary = false
    desired_area = 0.4
    smooth_triangulation = true
  []
  [hex_assembly1_R0_rename_boundary_id]
    type = RenameBoundaryGenerator
    input = hex_assembly1_R0
    old_boundary = '1'
    new_boundary = '11'
  []
  [hex_assembly1_R0_meta]
    type = AddMetaDataGenerator
    input = hex_assembly1_R0_rename_boundary_id
  []
  #
  # Assembly type 1 R1
  #
  [assembly1_R1]
    type = PatternedHexMeshGenerator
    inputs = 'fake_pin fuel_pin_R1 heat_pipe_pin'
    rotate_angle = 0
    pattern_boundary = none
    pattern = '   0 1 1 0;
                 1 1 2 1 1;
                1 2 1 1 2 1;
               0 1 1 2 1 1 0;
                1 2 1 1 2 1;
                 1 1 2 1 1;
                  0 1 1 0'
    id_name = 'pin_id'
  []
  # delete fake cell
  [assembly1_R1_del]
    type = BlockDeletionGenerator
    input = assembly1_R1
    block = '${to_remove_tri_block_id}'
  []
  [assembly1_R1_outer_hex]
    type = HexagonConcentricCircleAdaptiveBoundaryMeshGenerator
    hexagon_size_style = apothem
    hexagon_size = '${asm_apothem}'
    # Re-use pin_cell_sectors_per_side, the number of sectors will be overridden by automatic refinement by the subsequent XYDG
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    background_block_ids = '${monolith_tri_block_id}'
    background_block_names = '${monolith_tri_block_name}'
  []
  # add background meshes of hex assembly and merge with hex cells
  [hex_assembly1_R1]
    type = XYDelaunayGenerator
    boundary = 'assembly1_R1_outer_hex'
    holes = 'assembly1_R1_del'
    stitch_holes = 'true'
    refine_holes = 'false'
    add_nodes_per_boundary_segment = ${hex_assembly_xydg_nodes_to_add}
    output_boundary = 10000
    # Get a bunch of errors if this is set to 'true'
    refine_boundary = false
    desired_area = 0.4
    smooth_triangulation = true
  []
  [hex_assembly1_R1_rename_boundary_id]
    type = RenameBoundaryGenerator
    input = hex_assembly1_R1
    old_boundary = '1'
    new_boundary = '11'
  []
  [hex_assembly1_R1_meta]
    type = AddMetaDataGenerator
    input = hex_assembly1_R1_rename_boundary_id
  []
  #
  # Assembly type 1 R2
  #
  [assembly1_R2]
    type = PatternedHexMeshGenerator
    inputs = 'fake_pin fuel_pin_R2 heat_pipe_pin'
    rotate_angle = 0
    pattern_boundary = none
    pattern = '   0 1 1 0;
                 1 1 2 1 1;
                1 2 1 1 2 1;
               0 1 1 2 1 1 0;
                1 2 1 1 2 1;
                 1 1 2 1 1;
                  0 1 1 0'
    id_name = 'pin_id'
    #external_boundary_id = '${assembly1_boundary_id}'
    #external_boundary_name = '${assembly1_boundary_name}'
  []
  # delete fake cell
  [assembly1_R2_del]
    type = BlockDeletionGenerator
    input = assembly1_R2
    block = '${to_remove_tri_block_id}'
    #new_boundary = 'inner_bdy'
  []
  [assembly1_R2_outer_hex]
    type = HexagonConcentricCircleAdaptiveBoundaryMeshGenerator
    hexagon_size_style = apothem
    hexagon_size = '${asm_apothem}'
    # Re-use pin_cell_sectors_per_side, the number of sectors will be overridden by automatic refinement by the subsequent XYDG
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    background_block_ids = '${monolith_tri_block_id}'
    background_block_names = '${monolith_tri_block_name}'
  []
  # add background meshes of hex assembly and merge with hex cells
  [hex_assembly1_R2]
    type = XYDelaunayGenerator
    boundary = 'assembly1_R2_outer_hex'
    holes = 'assembly1_R2_del'
    stitch_holes = 'true'
    refine_holes = 'false'
    add_nodes_per_boundary_segment = ${hex_assembly_xydg_nodes_to_add}
    output_boundary = 10000
    # Get a bunch of errors if this is set to 'true'
    refine_boundary = false
    desired_area = 0.4
    smooth_triangulation = true
  []
  [hex_assembly1_R2_rename_boundary_id]
    type = RenameBoundaryGenerator
    input = hex_assembly1_R2
    old_boundary = '1'
    new_boundary = '11'
  []
  [hex_assembly1_R2_meta]
    type = AddMetaDataGenerator
    input = hex_assembly1_R2_rename_boundary_id
  []
  #
  # Assembly type 1 R3
  #
  [assembly1_R3]
    type = PatternedHexMeshGenerator
    inputs = 'fake_pin fuel_pin_R3 heat_pipe_pin'
    rotate_angle = 0
    pattern_boundary = none
    pattern = '   0 1 1 0;
                 1 1 2 1 1;
                1 2 1 1 2 1;
               0 1 1 2 1 1 0;
                1 2 1 1 2 1;
                 1 1 2 1 1;
                  0 1 1 0'
    id_name = 'pin_id'
    #external_boundary_id = '${assembly1_boundary_id}'
    #external_boundary_name = '${assembly1_boundary_name}'
  []
  # delete fake cell
  [assembly1_R3_del]
    type = BlockDeletionGenerator
    input = assembly1_R3
    block = '${to_remove_tri_block_id}'
    #new_boundary = 'inner_bdy'
  []
  [assembly1_R3_outer_hex]
    type = HexagonConcentricCircleAdaptiveBoundaryMeshGenerator
    hexagon_size_style = apothem
    hexagon_size = '${asm_apothem}'
    # Re-use pin_cell_sectors_per_side, the number of sectors will be overridden by automatic refinement by the subsequent XYDG
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    background_block_ids = '${monolith_tri_block_id}'
    background_block_names = '${monolith_tri_block_name}'
  []
  # add background meshes of hex assembly and merge with hex cells
  [hex_assembly1_R3]
    type = XYDelaunayGenerator
    boundary = 'assembly1_R3_outer_hex'
    holes = 'assembly1_R3_del'
    stitch_holes = 'true'
    refine_holes = 'false'
    add_nodes_per_boundary_segment = ${hex_assembly_xydg_nodes_to_add}
    output_boundary = 10000
    # Get a bunch of errors if this is set to 'true'
    refine_boundary = false
    desired_area = 0.4
    smooth_triangulation = true
  []
  [hex_assembly1_R3_rename_boundary_id]
    type = RenameBoundaryGenerator
    input = hex_assembly1_R3
    old_boundary = '1'
    new_boundary = '11'
  []
  [hex_assembly1_R3_meta]
    type = AddMetaDataGenerator
    input = hex_assembly1_R3_rename_boundary_id
  []
  #
  # Assembly type 3 (with CR hole)
  #
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 3: The identical 2D fuel assembly meshes; heat pipe pin cell meshes are in green and the fuel pin cell meshes are in red.

The last fuel pin assembly mesh generated includes a control rod channel. The same steps as above are followed, but block ids must be assigned to the larger, to be deleted, void region before being meshed. Then the control rod hole is carved and stitched back to the hexagonal assembly mesh.

  [assembly3]
    type = PatternedHexMeshGenerator
    inputs = 'fake_pin fuel3_pin heat_pipe_pin fake_pin_2'
    rotate_angle = 0
    pattern_boundary = none
    pattern = '0 1 1 0;
              1 1 2 1 1;
             1 2 3 3 2 1;
            0 1 3 3 3 1 0;
             1 2 3 3 2 1;
              1 1 2 1 1;
               0 1 1 0'
    id_name = 'pin_id'
    #external_boundary_id = '${assembly3_boundary_id}'
    #external_boundary_name = '${assembly3_boundary_name}'
  []
  [assmebly3_fake2_boundary]
    type = SideSetsAroundSubdomainGenerator
    block = ${to_remove2_tri_block_id}
    input = assembly3
    new_boundary = 867
  []
  # delete outer fake pin cells
  [assembly3_del_outer]
    type = BlockDeletionGenerator
    input = assmebly3_fake2_boundary
    block = '${to_remove_tri_block_id}'
    new_boundary = 53
  []
  # This creates a void of 7 pin cells in the center where fake_pin_2 was defined
  [assembly3_del_center]
    type = BlockDeletionGenerator
    input = assembly3_del_outer
    block = '${to_remove2_tri_block_id}'
    new_boundary = 76
  []
  # The deletion has created a void where the deleted pin cells were. We now assign a block ID to the deleted area
  [assembly3_rebuild_center]
    type = LowerDBlockFromSidesetGenerator
    input = assembly3_del_center
    sidesets = '76'
    new_block_id = '6123'
    new_block_name = 'rebuilt_center'
  []
  # Next we mesh the area with the new block ID, removing the void
  # In reality, we need to use XYDG to actually "mesh" this, this is just an intermediate step for using XYDG
  [assembly3_remesh_center]
    type = BlockToMeshConverterGenerator
    input = assembly3_rebuild_center
    target_blocks = 'rebuilt_center'
  []
  # Hole to carve using ParsedCurveGenerator
  [assembly3_carved_hole]
    type = ParsedCurveGenerator
    x_formula = '${hole_radius}*cos(t)'
    y_formula = 'y1:=${hole_radius}*sin(t);
                 y2:=${hole_radius}*sin(t);
                 if (t<${fparse pi},y1,y2)'
    section_bounding_t_values = '0.0 ${fparse pi} ${fparse 2.0*pi}'
    # 24 segments total around the hole can be refined based on the pin refinement
    nums_segments = '12 12'
    is_closed_loop = true
  []
  # Next we use XYDelaunayGenerator (XYDG) to carve the hole in the area of the pin cells we designated for the hole
  [assembly3_center_area_with_hole]
    type = XYDelaunayGenerator
    boundary = 'assembly3_remesh_center'
    holes = 'assembly3_carved_hole'
    hole_boundaries = 'center_hole_boundary'
    add_nodes_per_boundary_segment = 0
    output_boundary = 10010 # xy_output_boundary
    refine_boundary = false
    smooth_triangulation = true
    desired_area = 0.5
    output_subdomain_name = ${monolith_tri_block_id}
  []
  # Next we can stitch the area meshed by XYDG, which is the deleted pin cell area OUTSIDE of the hole, to the hex assembly mesh
  [assembly3_center_w_hole_void]
    type = StitchedMeshGenerator
    inputs = 'assembly3_del_center assembly3_center_area_with_hole'
    stitch_boundaries_pairs = '76 10010'
    prevent_boundary_ids_overlap = true
  []
  # Since we want the hole meshed we need to get the hole boundary and use XYDG to mesh it as well
  [assembly3_mesh_center_hole]
    type = XYDelaunayGenerator
    boundary = 'assembly3_center_w_hole_void'
    add_nodes_per_boundary_segment = 0
    input_boundary_names = center_hole_boundary # xy_output_boundary
    refine_boundary = false
    smooth_triangulation = true
    output_subdomain_name = ${rod_channel_block_id}
    output_boundary = to_be_stitched
    desired_area = 0.8
  []
  # Now we must stitch the meshed hole to the center area with the hole void
  [assembly3_center_stitched]
    type = StitchedMeshGenerator
    inputs = 'assembly3_center_w_hole_void assembly3_mesh_center_hole'
    stitch_boundaries_pairs = 'center_hole_boundary to_be_stitched'
    prevent_boundary_ids_overlap = true
  []
  [assembly3_outer_hex]
    type = HexagonConcentricCircleAdaptiveBoundaryMeshGenerator
    hexagon_size_style = apothem
    hexagon_size = '${asm_apothem}'
    # Re-use pin_cell_sectors_per_side, the number of sectors will be overridden by automatic refinement by the subsequent XYDG
    num_sectors_per_side = '${pin_cell_sectors_per_side}'
    background_block_ids = '${monolith_tri_block_id}'
    background_block_names = '${monolith_tri_block_name}'
  []
  # add background meshes of hex assembly and merge with hex cells
  [hex_assembly3]
    type = XYDelaunayGenerator
    boundary = 'assembly3_outer_hex'
    holes = 'assembly3_center_stitched'
    stitch_holes = 'true'
    refine_holes = 'false'
    add_nodes_per_boundary_segment = ${hex_assembly_xydg_nodes_to_add}
    output_boundary = 10000
    # Get a bunch of errors if this is set to 'true'
    refine_boundary = false
    desired_area = 0.4
    smooth_triangulation = true
  []
  [hex_assembly3_rename_boundary_id]
    type = RenameBoundaryGenerator
    input = hex_assembly3
    old_boundary = '1'
    new_boundary = '13'
  []
  [hex_assembly3_meta]
    type = AddMetaDataGenerator
    input = hex_assembly3_rename_boundary_id
  []
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 4: The 2D fuel assembly mesh containing a control rod channel in the center; heat pipe pin cell meshes are in green and the fuel pin cell meshes are in red.

Hexagonal Core Assembly

The hexagonal core assembly mesh is generated using the previous step's fuel pin assembly meshes. The block ids are renamed to separate the monolith triangular elements. Then the outer core ring boundary is created.

  [core1]
    type = PatternedHexMeshGenerator
    inputs = 'hex_assembly1_R0_meta hex_assembly1_R1_meta hex_assembly1_R2_meta hex_assembly1_R3_meta hex_assembly3_meta'
    rotate_angle = 30
    pattern_boundary = none
    pattern = '
          3 2 2 2 2 2 3;
         2 1 1 1 1 1 1 2;
        2 1 0 0 0 0 0 1 2;
       2 1 0 4 0 0 4 0 1 2;
      2 1 0 0 0 4 0 0 0 1 2;
     2 1 0 0 4 0 0 4 0 0 1 2;
    3 1 0 4 0 0 4 0 0 4 0 1 3;
     2 1 0 0 4 0 0 4 0 0 1 2;
      2 1 0 0 0 4 0 0 0 1 2;
       2 1 0 4 0 0 4 0 1 2;
        2 1 0 0 0 0 0 1 2;
         2 1 1 1 1 1 1 2;
          3 2 2 2 2 2 3'
    id_name = 'assembly_id'
    external_boundary_id = '${core_boundary_id}'
    external_boundary_name = '${core_boundary_name}'
  []
  # separate monolith tri
  [rename_block_ids_mono]
    type = RenameBlockGenerator
    input = 'core1'
    old_block = '0'
    new_block = '${monolith_tri_block_id}'
  []
  # Use parsed curve because we will remesh it with XYDG
  [outer_core_ring]
    type = ParsedCurveGenerator
    x_formula = '${outer_core_radius}*cos(t)'
    y_formula = 'y1:=${outer_core_radius}*sin(t);
                 y2:=${outer_core_radius}*sin(t);
                 if (t<${fparse pi},y1,y2)'
    section_bounding_t_values = '0.0 ${fparse pi} ${fparse 2.0*pi}'
    nums_segments = '40 40'
    is_closed_loop = true
  []
  # Mesh control drums using PolygonConcentricCircleMeshGenerator
  # and then AzimuthalBlockSplitGenerator for part of the mesh
  # then use XYDG to merge the two
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 5: The 2D hexagonal core assembly mesh.

Control Drum Meshes

The meshes for the 12 control drums are then generated. The control drum base mesh is first generated, then the outer polygon area is deleted to keep only the circular control drum.

  [control_drum_base]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    polygon_size = ${control_drum_polygon_apothem}
    polygon_size_style = apothem
    num_sectors_per_side = ${control_drum_num_sectors}
    background_intervals = 1
    background_block_ids = '${to_remove_quad_block_id}'
    background_block_names = '${to_remove_quad_block_name}'
    ring_radii = '${control_drum_inner_radius} ${control_drum_outer_radius}'
    ring_intervals = '1 2'
    ring_block_ids = '${drum_reflector_quad_block_id} ${drum_vary_block_id}'
    ring_block_names = '${drum_reflector_quad_block_name} ${drum_vary_block_name}'
    preserve_volumes = true
    quad_center_elements = true
    #is_control_drum = true
  []
  [control_drum_01]
    type = AzimuthalBlockSplitGenerator
    input = control_drum_base
    start_angle = 300
    angle_range = ${control_drum_absorber_angle}
    old_blocks = ${drum_vary_block_id}
    new_block_ids = ${drum_absorber_block_id}
    new_block_names = ${drum_absorber_block_name}
    preserve_volumes = true
  []
  # Delete outer polygon area, keeping only circles
  [control_drum_01_delete]
    type = BlockDeletionGenerator
    input = control_drum_01
    block = '${to_remove_quad_block_id}'
    new_boundary = ${drum_boundary_id}
  []
(microreactors/gHPMR/2D_gHPMR_Final.i)

The control drum mesh is rotated then translated multiple times to account for every position and placement of the drums in the core.

  [control_drum_S1_A]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord} ${control_drum_y_coord} 0'
  []
  [control_drum_S1_B]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord} -${control_drum_y_coord} 0'
  []
  # Rotate the control drum which is placed on another side
  [control_drum_S2]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = ROTATE
    vector_value = '60 0 0'
  []
  [control_drum_S3]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = ROTATE
    vector_value = '120 0 0'
  []
  [control_drum_S4]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = ROTATE
    vector_value = '180 0 0'
  []
  [control_drum_S5]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = ROTATE
    vector_value = '240 0 0'
  []
  [control_drum_S6]
    type = TransformGenerator
    input = control_drum_01_delete
    transform = ROTATE
    vector_value = '300 0 0'
  []
  [control_drum_S4_A]
    type = TransformGenerator
    input = control_drum_S4
    transform = TRANSLATE
    vector_value = '${control_drum_x_coord} ${control_drum_y_coord} 0'
  []
  [control_drum_S4_B]
    type = TransformGenerator
    input = control_drum_S4
    transform = TRANSLATE
    #vector_value = '120.1 -30.31 0'
    vector_value = '${control_drum_x_coord} -${control_drum_y_coord} 0'
  []
  [control_drum_S5_A]
    type = TransformGenerator
    input = control_drum_S5
    transform = TRANSLATE
    vector_value = '${control_drum_x_coord_s5_b} ${control_drum_y_coord_s5_b} 0'
  []
  [control_drum_S5_B]
    type = TransformGenerator
    input = control_drum_S5
    transform = TRANSLATE
    vector_value = '${control_drum_x_coord_s5_a} ${control_drum_y_coord_s5_a} 0'
  []
  [control_drum_S6_A]
    type = TransformGenerator
    input = control_drum_S6
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord_s5_a} ${control_drum_y_coord_s5_a} 0'
  []
  [control_drum_S6_B]
    type = TransformGenerator
    input = control_drum_S6
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord_s5_b} ${control_drum_y_coord_s5_b} 0'
  []
  [control_drum_S2_A]
    type = TransformGenerator
    input = control_drum_S2
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord_s5_b} -${control_drum_y_coord_s5_b} 0'
  []
  [control_drum_S2_B]
    type = TransformGenerator
    input = control_drum_S2
    transform = TRANSLATE
    vector_value = '-${control_drum_x_coord_s5_a} -${control_drum_y_coord_s5_a} 0'
  []
  [control_drum_S3_A]
    type = TransformGenerator
    input = control_drum_S3
    transform = TRANSLATE
    vector_value = '${control_drum_x_coord_s5_b} -${control_drum_y_coord_s5_b} 0'
  []
  [control_drum_S3_B]
    type = TransformGenerator
    input = control_drum_S3
    transform = TRANSLATE
    vector_value = '${control_drum_x_coord_s5_a} -${control_drum_y_coord_s5_a} 0'
  []
  # Polygons in the outer reflector region in an effort to reduce areas meshed by XYDG
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 6: Six control rods with different orientations.

Reflector Mesh

The mesh for the reflector is generated using a lattice of polygonal meshes to keep a more structured mesh, and avoid generating a 2D mesh in a large area. The mesh is then translated several times to account for every position and placement of reflectors in the core.

  [reflector_polygon]
    type = PolygonConcentricCircleMeshGenerator
    num_sides = 6
    polygon_size = ${reflector_polygon_size}
    polygon_size_style = apothem
    num_sectors_per_side = ${reflector_polygon_num_sectors_per_side}
    ring_intervals = 1
    ring_radii = ${reflector_ring_radius}
    ring_block_ids = '${reflector_quad_block_id}'
    ring_block_names = '${reflector_quad_block_name}'
    background_intervals = 1
    background_block_ids = '${to_remove_quad_block_id}'
    background_block_names = '${to_remove_quad_block_name}'
    preserve_volumes = true
    quad_center_elements = true
    #is_control_drum = true
  []
  [reflector_polygon_delete]
    type = BlockDeletionGenerator
    input = reflector_polygon
    block = '${to_remove_quad_block_id}'
    new_boundary = ${drum_boundary_id}
  []
  [reflector_polygon_01]
    type = TransformGenerator
    input = reflector_polygon_delete
    transform = TRANSLATE
    vector_value = '${reflector_polygon_x_coord} 0 0'
  []
  [reflector_polygon_02]
    type = TransformGenerator
    input = reflector_polygon_delete
    transform = TRANSLATE
    vector_value = '${reflector_polygon_alt_x_coord} ${reflector_polygon_alt_y_coord} 0'
  []
  [reflector_polygon_04]
    type = TransformGenerator
    input = reflector_polygon_delete
    transform = TRANSLATE
    vector_value = '-${reflector_polygon_x_coord} 0 0'
  []
  # add background meshes of hex assembly and merge with hex cells
(microreactors/gHPMR/2D_gHPMR_Final.i)

Outer Core Mesh

Lastly, the core mesh is merged with the control drum and reflector meshes to generate a final core mesh which includes the outer core area. Block ids are renamed to keep triangular and quadrilateral elements separate. The outer vessel mesh is generated and sidesets are added to specify the radial boundary of the reactor vessel.

  [outer_core_mesh]
    type = XYDelaunayGenerator
    boundary = 'outer_core_ring'
    #holes = 'core1 control_drum_S1_A control_drum_S1_B control_drum_S4_A control_drum_S4_B control_drum_S5_A control_drum_S5_B control_drum_S6_A control_drum_S6_B control_drum_S2_A control_drum_S2_B control_drum_S3_A control_drum_S3_B'
    holes = 'rename_block_ids_mono control_drum_S1_A control_drum_S1_B control_drum_S4_A control_drum_S4_B control_drum_S5_A control_drum_S5_B control_drum_S6_A control_drum_S6_B control_drum_S2_A control_drum_S2_B control_drum_S3_A control_drum_S3_B'
    stitch_holes = 'true true true true true true true true true true true true true'
    refine_holes = 'false false false false false false false false false false false false false'
    #add_nodes_per_boundary_segment = 200
    output_boundary = 10002
    refine_boundary = true
    desired_area = 6.0
    smooth_triangulation = true
  []
  # separate reflector tri and quad
  [rename_block_ids_reflector]
    type = RenameBlockGenerator
    input = outer_core_mesh
    old_block = '0 ${drum_reflector_quad_block_id}'
    new_block = '${reflector_tri_block_id} ${reflector_quad_block_id}'
  []
  [outer_cannister]
    type = PeripheralTriangleMeshGenerator
    input = rename_block_ids_reflector
    peripheral_ring_radius = ${outer_cannister_radius}
    peripheral_ring_num_segments = 100
    desired_area = 10
    peripheral_ring_block_name = ${outer_cannister_block_name}
  []
  [sideset_gen]
    type = ParsedGenerateSideset
    input = outer_cannister
    combinatorial_geometry = 'x*x+y*y>146.5*146.5'
    new_sideset_name = 'radial_boundary'
  []
(microreactors/gHPMR/2D_gHPMR_Final.i)

Figure 8: The 2D final core assembly mesh featuring 12 control drums, exterior reactor vessel ring in red, fuel assemblies in yellow, and fuel assemblies with control rod channels in pink.

Figure 9: Closeup of the 2D final core assembly mesh featuring control drums in gray and fuel assemblies with and without control rod channels.

Extrusion to 3D Specifications

The spacial discretization specifications are summarized below.

Table 1: The 2D mesh can be extruded to form a 3D mesh. Table 1 summarizes the extrusion specifications in the gHPMR model, from Ortensi et al. (2024).

Spacial DiscretizationValue
Number of Axial Elements in Evaporator Section18
Number of Axial Elements in Adiabatic Section4
Number of Axial Elements in Condenser Section18
Number of Radial Elements in Wick Region2
Number of Radial Elements in Annular Gap Region2
Number of Radial Elements in Cladding Region2

References

  1. Javier Ortensi, Mustafa K. Jaradat, Joshua Hansel, and Stefano Terlizzi. The monolithic heat pipe microreactor reference plant model. Technical Report INL/RPT-24-77914, Idaho National Laboratory, 4 2024.[BibTeX]