Hex20Generator

Converts a HEX27 mesh to a HEX20 mesh, while optionally preserving circular edges (which were faceted) in the HEX27 mesh.

Description

This mesh generator is used to convert a HEX27 mesh into a HEX20 mesh, specifically for compatibility with NekRS's exo2nek utility that generates a NekRS mesh (the custom .re2 format). This mesh generator will:

  • Take a HEX27 mesh and convert it into an equivalent HEX20 mesh

  • Optionally move nodes to be conformal with a cylinder. NekRS uses a high-order spectral element solution, which will exactly represent the cylinder surface with its Gauss-Lobatto-Legendre (GLL) points (as long as the HEX20 elements have their mid-side nodes one the cylinder, which is what this mesh generator does for you)

  • Optionally move nodes at polygon corners to a cylindrical radius of curvature. This allows NekRS to exactly represent curved corners of meshes that represent regular polygons, such as for curving the corners of a mesh representing a six-sided duct.

commentnote:"Have a HEX8 mesh instead of a HEX27 mesh?

If you have a HEX8 mesh, you can convert it to a HEX27 mesh by adding second_order = true in a separate MOOSE file that generates your mesh (which can be as simple as just reading the mesh from a file with a FileMeshGenerator, like this

[Mesh]
  [file]
    type = FileMeshGenerator
    file = mesh.e
  []

  second_order = true
[]

Just for illustration, if you named the above as mesh.i, you can then run cardinal-opt -i mesh.i --mesh-only to get a new mesh, mesh_in.e that is a HEX27 mesh. Then, you can use this mesh generator.

warningwarning

This mesh generator has very limited error checking, and will not protect you from inverted elements or other errors. Always be sure to check your mesh output for correct behavior.

Example

This example converts from a HEX27 mesh to a HEX20 mesh, while also moving the outer boundary (rmax) to a cylinder with radius of 0.25.

[Mesh]
  [tube]
    type = FileMeshGenerator
    file = tube_in.e
  []
  [to_hex20]
    type = Hex20Generator
    input = tube
    boundary = 'rmax'
    radius = '0.25'
  []

  parallel_type = replicated
[]
(test/tests/meshgenerators/second_order_hex_generator/convert_outer.i)

Figure 1 shows the meshes involved in this example; the original mesh (tube_in.e) is a HEX27 mesh, which gets converted to a HEX20 mesh (and we also moved one boundary to a cylinder surface). Then, the GLL quadrature points used in NekRS for a 5th order spectral element polynomial basis is shown on the right, which by having the curved HEX20 elements, moves the quadrature points to also be on the cylinder.

Figure 1: Input, output, and NekRS meshes involved in mesh conversion example

For a second example, consider the case where you have one boundary that you want to move with multiple origins. In this case, list the points in origins for each boundary, with a semicolon separating the origins to be used for each boundary.

[Mesh]
  [fluid]
    type = FileMeshGenerator
    file = fluid.exo
  []
  [to_hex20]
    type = Hex20Generator
    input = fluid
    boundary = '1'
    radius = '${fparse 7.646e-3 / 2.0}'
    origins = '+0.00000000 +0.00000000 +0.00000000
               +0.00000000 +0.00896570 +0.00000000
               -0.00776452 +0.00448285 +0.00000000
               -0.00776452 -0.00448285 +0.00000000
               +0.00000000 -0.00896570 +0.00000000
               +0.00776452 -0.00448285 +0.00000000
               +0.00776452 +0.00448285 +0.00000000'
  []

  parallel_type = replicated
[]
(test/tests/meshgenerators/second_order_hex_generator/multiple_origins.i)

Figure 2 shows the meshes involved in this second example; the original mesh (fluid.exo) is a HEX27 mesh, which gets converted to a HEX20 mesh where boundary 1 is moved according to the nearest origin from a set of 7 different origins. This allows you to group all the surfaces into one sideset, but move them to unique origins.

Figure 2: Input and output meshes when using multiple origins for a single sideset

When your mesh has boundary layers that are thin relative to the mesh movement needed to fit to cylinder surfaces, it is possible to obtain inverted elements. You can move the elements on the "other" side of the element face lying on the cylinder by setting the layers variable. With this parameter, if node AA on face 0 moves by Δx\Delta x to get onto the cylinder surface, then the same displacement is applied to that node's "pair" on the opposite face. An example of this usage is shown below, where nodes not on the boundary of interest are still moved in order to better mesh the boundary layer. Figure 3 shows the effect of setting layers (which defaults to zero) to 1.

[Mesh]
  [fluid]
    type = FileMeshGenerator
    file = fluid_with_bl.exo
  []
  [to_hex20]
    type = Hex20Generator
    input = fluid
    boundary = '1'
    radius = '${fparse 7.646e-3 / 2.0}'
    origins = '+0.00000000 +0.00000000 +0.00000000
               +0.00000000 +0.00896570 +0.00000000
               -0.00776452 +0.00448285 +0.00000000
               -0.00776452 -0.00448285 +0.00000000
               +0.00000000 -0.00896570 +0.00000000
               +0.00776452 -0.00448285 +0.00000000
               +0.00776452 +0.00448285 +0.00000000'
    layers = '1'
  []

  parallel_type = replicated
[]
(test/tests/meshgenerators/second_order_hex_generator/layers.i)

Figure 3: Input and output meshes when using different layers settings

You can also set the layers to be greater than 1, in which case multiple layers of boundary elements are moved. An example of this usage is shown below, where elements 3 layers deep are moved to match the cylinder surface. Figure 4 shows the effect of setting layers (which defaults to zero) to 3.

[Mesh]
  [fluid]
    type = FileMeshGenerator
    file = fluid_with_multiple_bl.exo
  []
  [to_hex20]
    type = Hex20Generator
    input = fluid
    boundary = '1'
    radius = '${fparse 7.646e-3 / 2.0}'
    origins = '+0.00000000 +0.00000000 +0.00000000
               +0.00000000 +0.00896570 +0.00000000
               -0.00776452 +0.00448285 +0.00000000
               -0.00776452 -0.00448285 +0.00000000
               +0.00000000 -0.00896570 +0.00000000
               +0.00776452 -0.00448285 +0.00000000
               +0.00776452 +0.00448285 +0.00000000'
    layers = '3'
  []

  parallel_type = replicated
[]
(test/tests/meshgenerators/second_order_hex_generator/three_layers.i)

Figure 4: Input and output meshes when using layers = 3

Finally, you can move the corners of your mesh to a specified radius of curvature. In the example below, the original mesh has an outer boundary that matches a regular six-sided polygon. We move the corners, as well as attached boundary layers, to have a radius of curvature.

[Mesh]
  [fluid]
    type = FileMeshGenerator
    file = with_bl.exo
  []
  [rotate]
    type = TransformGenerator
    input = fluid
    transform = rotate
    vector_value = '30.0 0.0 0.0'
  []
  [to_hex20]
    type = Hex20Generator
    input = rotate
    boundaries_to_rebuild = '1 2 3 4'

    curve_corners = true
    polygon_sides = 6
    polygon_size = 0.018001405522227287
    polygon_boundary = '4'
    polygon_layers = 3
    corner_radius = 0.002
  []

  parallel_type = replicated
[]
(test/tests/meshgenerators/polygon_corners/six_with_bl.i)

Figure 5: Input and output meshes when enforcing radius of curvature at polygon corners

Input Parameters

  • inputThe mesh we want to modify

    C++ Type:MeshGeneratorName

    Controllable:No

    Description:The mesh we want to modify

Required Parameters

  • axiszAxis of the mesh about which to build the circular surface(s)

    Default:z

    C++ Type:MooseEnum

    Options:x, y, z

    Controllable:No

    Description:Axis of the mesh about which to build the circular surface(s)

  • boundaries_to_rebuildBoundary(s) to retain from the original mesh in the new mesh; if not specified, all original boundaries are kept.

    C++ Type:std::vector<BoundaryName>

    Controllable:No

    Description:Boundary(s) to retain from the original mesh in the new mesh; if not specified, all original boundaries are kept.

  • boundaryBoundary(s) to enforce a circular surface

    C++ Type:std::vector<BoundaryName>

    Controllable:No

    Description:Boundary(s) to enforce a circular surface

  • corner_radiusWhen curving corners, the radius of curvature of the corners

    C++ Type:double

    Controllable:No

    Description:When curving corners, the radius of curvature of the corners

  • curve_cornersFalseWhether to move elements to respect radius of curvature of polygon corners

    Default:False

    C++ Type:bool

    Controllable:No

    Description:Whether to move elements to respect radius of curvature of polygon corners

  • layersNumber of layers to sweep for each boundary when forming the circular surfaces; if not specified, all values default to 0

    C++ Type:std::vector<unsigned int>

    Controllable:No

    Description:Number of layers to sweep for each boundary when forming the circular surfaces; if not specified, all values default to 0

  • originsOrigin(s) about which to form the circular surfaces; if not specified, all values default to (0, 0, 0)

    C++ Type:std::vector<std::vector<double>>

    Controllable:No

    Description:Origin(s) about which to form the circular surfaces; if not specified, all values default to (0, 0, 0)

  • origins_filesOrigin(s) about which to form the circular surfaces, with a file of points provided for each boundary. If not specified, all values default to (0, 0, 0)

    C++ Type:std::vector<std::string>

    Controllable:No

    Description:Origin(s) about which to form the circular surfaces, with a file of points provided for each boundary. If not specified, all values default to (0, 0, 0)

  • polygon_boundaryBoundary to enforce radius of curvature for polygon corners

    C++ Type:BoundaryName

    Controllable:No

    Description:Boundary to enforce radius of curvature for polygon corners

  • polygon_layer_smoothingWhen curving corners, the multiplicative factor to apply to each boundary layer; if not specified, all values default to 1.0

    C++ Type:std::vector<double>

    Controllable:No

    Description:When curving corners, the multiplicative factor to apply to each boundary layer; if not specified, all values default to 1.0

  • polygon_layers0When curving corners, the number of layers to sweep for each polygon corner

    Default:0

    C++ Type:unsigned int

    Controllable:No

    Description:When curving corners, the number of layers to sweep for each polygon corner

  • polygon_originsOrigin(s) about which to curve the polygon corners; if not specified, defaults to (0, 0, 0)

    C++ Type:std::vector<std::vector<double>>

    Controllable:No

    Description:Origin(s) about which to curve the polygon corners; if not specified, defaults to (0, 0, 0)

  • polygon_sidesWhen curving corners, the number of sides of the polygon to use for identifying corners

    C++ Type:unsigned int

    Controllable:No

    Description:When curving corners, the number of sides of the polygon to use for identifying corners

  • polygon_sizeWhen curving corners, the size of the polygon (measured as distance from center to a corner) to use for identifying corners

    C++ Type:double

    Controllable:No

    Description:When curving corners, the size of the polygon (measured as distance from center to a corner) to use for identifying corners

  • radiusRadius(es) of the circular surfaces

    C++ Type:std::vector<double>

    Controllable:No

    Description:Radius(es) of the circular surfaces

  • rotation_angle0When curving corners, the rotation angle (degrees) needed to apply to the original mesh to get a polygon boundary with one side horizontal

    Default:0

    C++ Type:double

    Controllable:No

    Description:When curving corners, the rotation angle (degrees) needed to apply to the original mesh to get a polygon boundary with one side horizontal

  • show_infoFalseWhether or not to show mesh info after generating the mesh (bounding box, element types, sidesets, nodesets, subdomains, etc)

    Default:False

    C++ Type:bool

    Controllable:No

    Description:Whether or not to show mesh info after generating the mesh (bounding box, element types, sidesets, nodesets, subdomains, etc)

Optional Parameters

  • control_tagsAdds user-defined labels for accessing object parameters via control logic.

    C++ Type:std::vector<std::string>

    Controllable:No

    Description:Adds user-defined labels for accessing object parameters via control logic.

  • enableTrueSet the enabled status of the MooseObject.

    Default:True

    C++ Type:bool

    Controllable:No

    Description:Set the enabled status of the MooseObject.

Advanced Parameters

Input Files