Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hexahedral Metrics

automesh metrics hex --help
Quality metrics for an all-hexahedral finite element mesh

Usage: automesh metrics hex [OPTIONS] --input <FILE> --output <FILE>

Options:
  -i, --input <FILE>   Mesh input file (exo | inp | stl)
  -o, --output <FILE>  Quality metrics output file (csv | npy)
  -q, --quiet          Pass to quiet the terminal output
  -h, --help           Print help

automesh implements the following hexahedral element quality metrics1:

  • Maximum edge ratio
  • Minimum scaled Jacobian
  • Maximum skew
  • Element volume

A brief description of each metric follows.

Maximum Edge Ratio

  • measures the ratio of the longest edge to the shortest edge in a mesh element.
  • A ratio of 1.0 indicates perfect element quality, whereas a very large ratio indicates bad element quality.
  • Knupp et al.1 (page 87) indicate an acceptable range of [1.0, 1.3].

Minimum Scaled Jacobian

  • evaluates the determinant of the Jacobian matrix at each of the corners nodes, normalized by the corresponding edge lengths, and returns the minimum value of those evaluations.
  • Interpretation
    • : Perfect rectangular element
    • : Element is valid (positive Jacobian)
    • : Element zero volume
    • : Invalid element (inverted/negative Jacobian)

Typically, mesh quality requirements specify for acceptable elements.

  • Knupp et al.1 (page 92) indicate an acceptable range of [0.5, 1.0], though in practice, minimum values as low as 0.2 and 0.3 are often used.

Figure. Illustration of minimum scaled Jacobian2 with acceptable range [0.3, 1.0].

Maximum Skew

  • Skew measures how much an element deviates from being a regular shape (e.g., in 3D, a cube or regular tetrahedron; in 2D, a square or equilateral triangle). A skew value of 0 indicates a perfectly regular shape, while higher values indicate increasing levels of distortion.
  • Knupp et al.1 (page 97) indicate an acceptable range of [0.0, 0.5].

Element Volume

  • Measures the volume of the element.

Unit Tests

Inspired by Figure 2 of Livesu et al.3 reproduced here below

we examine several unit test singleton elements and their metrics.

valencesingletonvolume
31.000000e0 (1.000)8.660253e-1 (0.866)5.000002e-1 (0.500)8.660250e-1 (0.866)
3' (noised)1.292260e0 (2.325) ** Cubit (aspect ratio): 1.2921.917367e-1 (0.192)6.797483e-1 (0.680)1.247800e0 (1.248)
41.000000e0 (1.000)1.000000e0 (1.000)0.000000e0 (0.000)1.000000e0 (1.000)
4' (noised)1.167884e0 (1.727) ** Cubit (aspect ratio): 1.1683.743932e-1 (0.374)4.864936e-1 (0.486)9.844008e-1 (0.984)
51.000000e0 (1.000)9.510566e-1 (0.951)3.090169e-1 (0.309)9.510570e-1 (0.951)
61.000000e0 (1.000)8.660253e-1 (0.866)5.000002e-1 (0.500)8.660250e-1 (0.866)
..................
101.000000e0 (1.000)5.877851e-1 (0.588)8.090171e-1 (0.809)5.877850e-1 (0.588)

Figure: Hexahedral metrics. Leading values are from automesh. Values in parenthesis are results from HexaLab.4 Items with ** indicate where automesh and Cubit agree, but HexaLab disagrees. Cubit uses the term Aspect Ratio for Edge Ratio for hexahedral elements. All values were also verified with Cubit.

The connectivity for all elements:

1,    2,    4,    3,    5,    6,    8,    7

with prototype:

The element coordinates follow:

# 3
    1,      0.000000e0,      0.000000e0,      0.000000e0
    2,      1.000000e0,      0.000000e0,      0.000000e0
    3,     -0.500000e0,      0.866025e0,      0.000000e0
    4,      0.500000e0,      0.866025e0,      0.000000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,     -0.500000e0,      0.866025e0,      1.000000e0
    8,      0.500000e0,      0.866025e0,      1.000000e0

# 3'
    1,      0.110000e0,      0.120000e0,     -0.130000e0
    2,      1.200000e0,     -0.200000e0,      0.000000e0
    3,     -0.500000e0,      1.866025e0,     -0.200000e0
    4,      0.500000e0,      0.866025e0,     -0.400000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,     -0.500000e0,      0.600000e0,      1.400000e0
    8,      0.500000e0,      0.866025e0,      1.200000e0

# 4
    1,      0.000000e0,      0.000000e0,      0.000000e0
    2,      1.000000e0,      0.000000e0,      0.000000e0
    3,      0.000000e0,      1.000000e0,      0.000000e0
    4,      1.000000e0,      1.000000e0,      0.000000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,      0.000000e0,      1.000000e0,      1.000000e0
    8,      1.000000e0,      1.000000e0,      1.000000e0

# 4'
    1,      0.100000e0,      0.200000e0,      0.300000e0
    2,      1.200000e0,      0.300000e0,      0.400000e0
    3,     -0.200000e0,      1.200000e0,     -0.100000e0
    4,      1.030000e0,      1.102000e0,     -0.250000e0
    5,     -0.001000e0,     -0.021000e0,      1.002000e0
    6,      1.200000e0,     -0.100000e0,      1.100000e0
    7,      0.000000e0,      1.000000e0,      1.000000e0
    8,      1.010000e0,      1.020000e0,      1.030000e0

# 5
    1,      0.000000e0,      0.000000e0,      0.000000e0
    2,      1.000000e0,      0.000000e0,      0.000000e0
    3,      0.309017e0,      0.951057e0,      0.000000e0
    4,      1.309017e0,      0.951057e0,      0.000000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,      0.309017e0,      0.951057e0,      1.000000e0
    8,      1.309017e0,      0.951057e0,      1.000000e0

# 6
    1,      0.000000e0,      0.000000e0,      0.000000e0
    2,      1.000000e0,      0.000000e0,      0.000000e0
    3,      0.500000e0,      0.866025e0,      0.000000e0
    4,      1.500000e0,      0.866025e0,      0.000000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,      0.500000e0,      0.866025e0,      1.000000e0
    8,      1.500000e0,      0.866025e0,      1.000000e0

# 10
    1,      0.000000e0,      0.000000e0,      0.000000e0
    2,      1.000000e0,      0.000000e0,      0.000000e0
    3,      0.809017e0,      0.587785e0,      0.000000e0
    4,      1.809017e0,      0.587785e0,      0.000000e0
    5,      0.000000e0,      0.000000e0,      1.000000e0
    6,      1.000000e0,      0.000000e0,      1.000000e0
    7,      0.809017e0,      0.587785e0,      1.000000e0
    8,      1.809017e0,      0.587785e0,      1.000000e0

Local Numbering Scheme

Nodes

The local numbering scheme for nodes of a hexahedral element:

       7---------6
      /|        /|
     / |       / |
    4---------5  |
    |  3------|--2
    | /       | /
    |/        |/
    0---------1
nodeconnected nodes
01, 3, 4
10, 2, 5
21, 3, 6
30, 2, 7
40, 5, 7
51, 4, 6
62, 5, 7
73, 4, 6

Faces

From the exterior of the element, view the (0, 1, 5, 4) face and unwarp the remaining faces; the six face normals now point out of the page. The local numbering scheme for faces of a hexahedral element:

              7---------6
              |         |
              |    5    |
              |         |
    7---------4---------5---------6---------7
    |         |         |         |         |
    |    3    |    0    |    1    |    2    |
    |         |         |         |         |
    3---------0---------1---------2---------3
              |         |
              |    4    |
              |         |
              3---------2
facenodes
00, 1, 5, 4
11, 2, 6, 5
22, 3, 7, 6
33, 0, 4, 7
43, 2, 1, 0
54, 5, 6, 7

Formulation

For a hexahedral element with eight nodes, the scaled Jacobian at each node is computed as:

where:

  • , , and are edge vectors emanating from the node,
  • is the cross product of the first two edge vectors, and
  • denotes the Euclidean norm.

The minimum scaled Jacobian for the element is:

Node Numbering Convention

The hexahedral element uses the following local node numbering (standard convention):

       7----------6
      /|         /|
     / |        / |
    4----------5  |
    |  |       |  |
    |  3-------|--2
    | /        | /
    |/         |/
    0----------1

Edge Vectors at Each Node

For each node , three edge vectors are defined that point to adjacent nodes. The connectivity follows this pattern:

NodeEdge Vector Definitions
0→ 1→ 3→ 4, ,
1→ 2→ 0→ 5, ,
2→ 3→ 1→ 6, ,
3→ 0→ 2→ 7, ,
4→ 7→ 5→ 0, ,
5→ 4→ 6→ 1, ,
6→ 5→ 7→ 2, ,
7→ 6→ 4→ 3, ,

where is the position of node .

Algorithm

  1. For each element in the mesh:

    a. Extract the 8 node indices from the connectivity array

    b. For each node :

    • Compute edge vectors: where , , are adjacent nodes per the table above

    • Compute cross product:

    • Compute scaled Jacobian:

    c. Take minimum over all 8 nodes:

  2. Return the vector of minimum scaled Jacobians, one per element

Implementation

This prototyptical Rust implementation calculates the MSJ by evaluating the Jacobian at each of the eight corners using the edges connected to that corner.

#![allow(unused)]
fn main() {
struct Vector3 {
    x: f64,
    y: f64,
    z: f64,
}

impl Vector3 {
    fn sub(a: &Vector3, b: &Vector3) -> Vector3 {
        Vector3 { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }
    }

    fn dot(a: &Vector3, b: &Vector3) -> f64 {
        a.x * b.x + a.y * b.y + a.z * b.z
    }

    fn cross(a: &Vector3, b: &Vector3) -> Vector3 {
        Vector3 {
            x: a.y * b.z - a.z * b.y,
            y: a.z * b.x - a.x * b.z,
            z: a.x * b.y - a.y * b.x,
        }
    }

    fn norm(&self) -> f64 {
        (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
    }
}

/// Calculates the Minimum Scaled Jacobian for a hexahedron.
/// nodes: An array of 8 points ordered by standard FEM convention.
pub fn min_scaled_jacobian(nodes: &[Vector3; 8]) -> f64 {
    // Define the three edges meeting at each of the 8 corners
    // Corners are ordered: 0-3 (bottom face), 4-7 (top face)
    // For each node index: (current_node, u_target, v_target, w_target)
    let corner_indices = [
        (0, 1, 3, 4), // Corner 0: edges to 1, 3, 4
        (1, 2, 0, 5), // Corner 1: edges to 2, 0, 5
        (2, 3, 1, 6), // Corner 2: edges to 3, 1, 6
        (3, 0, 2, 7), // Corner 3: edges to 0, 2, 7
        (4, 7, 5, 0), // Corner 4: edges to 7, 5, 0
        (5, 4, 6, 1), // Corner 5: edges to 4, 6, 1
        (6, 5, 7, 2), // Corner 6: edges to 5, 7, 2
        (7, 6, 4, 3), // Corner 7: edges to 6, 4, 3
    ];

    let mut min_sj = f64::MAX;
    const EPSILON: f64 = 1e-15; // Small threshold to avoid division by zero

    for &(curr, i, j, k) in &corner_indices {
        // Calculate edge vectors: u, v, w from current node
        let u = Vector3::sub(&nodes[i], &nodes[curr]);
        let v = Vector3::sub(&nodes[j], &nodes[curr]);
        let w = Vector3::sub(&nodes[k], &nodes[curr]);

        // Calculate n = u × v
        let n = Vector3::cross(&u, &v);

        // Calculate scaled Jacobian: (n · w) / (||u|| * ||v|| * ||w||)
        let det = Vector3::dot(&n, &w);
        let lengths = u.norm() * v.norm() * w.norm();

        // Avoid division by zero for degenerate elements
        let sj = if lengths > EPSILON {
            det / lengths
        } else {
            f64::NEG_INFINITY // Flag completely degenerate elements
        };

        if sj < min_sj {
            min_sj = sj;
        }
    }

    min_sj
}
}

Implementation Notes

The implementation evaluates all 8 nodes of each element and returns the minimum value. This ensures that element distortion at any corner is captured, as poor quality at a single node can affect finite element solution accuracy.

Node-based Refinement

Node-based refinement reframes the traditional minimum scaled Jacobian formulation, which finds a per element minimum value, as a per node weighted value calculation.

  • This calculation produces the incremental movement of the subject node that would improve the scaled Jacobian for the element at that node.
  • The development follows an incremental update of nodal position, similar to the update formulation of Laplace and Taubin smoothing.)

Node and Element Valence

We define nodal valence as the number of nodes connected via an element edge to the subject node. For a hexahedral mesh, the minimum nodal valence is three (for a node at an external corner of an element); the maximum nodal valence eight (for a node on the internal portion of the mesh).

We define element valence as the number of elements connected via an element connectivity to the subject node. For a hexahedral mesh, the minimum element valence is one (for a node at an external corner of an element); the maximum nodal valence is eight (for a node on the internal portion of the mesh). Let denote the element valence for a particular node.

For a given subject node with position connected to one-to-eight elements, for the element, , find the three edge-connected element nodes, located at position , and . We assume the node numbering convention given above, with

abc_e_definition

The current scaled Jacobian is defined by the current location of , holding positions of , constant:

From this definition, we define an ideal nodal position that exactly produces a scaled Jacobian of unity:

The ideal position is a point such that the vectors , , and are mutually orthogonal. How can we solve for in terms of , , and ?

We solve for by assuring that the three right triangles formed by and combinations of , , and satisfy Pythagorean's theorem. Let lengths

Then Pythagorean's theorem requires

This represents a system of three independent equations and three unknowns , , and .

Subtracting Eq. (18) from Eq. (17) and solving,

Before proceeding, we can further simplify the expressions of these equations by defining edge vectors that connect each of the points , , and that circle the path on . Let

Note that the square values of each of the three hypotenuses is , , and , respectively. Then

Solving,

The lengths , , and are now known. It is also known that in the local , , coordinate system spanned by the right-handed, orthonormal triad , , at point , the lengths , , , with their corresponding components of , , define the three components of , that is,

Weighting (aka Voting)

Any scheme for weighting of the connected elements can be adopted. Perhaps elements that lie on the surface should be given greater weighting than elements that lie on the interior. The effect would be to create higher quality element near the surface, and relatively lower quality element would be pushed into the interior of the volume. For a given element in the element valence of node , ,

For now, however, let's just explore the equal weighting scheme:

This is just the average of all ideal locations for each connected element .

Iteration

We define a gap vector as originating at the current position and terminating at the current ideal nodal position :

The quantity is geometrically interpreted as a search direction or gap vector, analogous to the gap vector defined for Laplace smoothing.

Let be the positive scaling factor for the gap .

Since

subdivision of this relationship into several substeps gives rise to an iterative approach. We typically select to avoid overshoot of the update, .

At iteration , we update the position of by an amount to as

with

Thus

and finally considering equal weighting for all connected elements

Sign Check

Because the derivation of finding involves squared terms, we must take one additional precaution to assure that the search direction is opposite the direction of the face normal of .

Let the face normal be defined as the cross product of any two edges of , e.g.,

In general, and are not colinear (they are colinear only for the special case where all lengths , , are equal). Nonetheless, for a non-inverted element with the search direction in the opposite direction of the face normal , the sign function (sgn) is used,

If an inverted element is encountered such that , then Eq. (39) should be modified to reverse the direction of , viz.

Compare the in Eq. (39) to the in Eq. (42).

References


  1. Knupp PM, Ernst CD, Thompson DC, Stimpson CJ, Pebay PP. The verdict geometric quality library. SAND2007-1751. Sandia National Laboratories (SNL), Albuquerque, NM, and Livermore, CA (United States); 2006 Mar 1. link ↩2 ↩3 ↩4

  2. Hovey CB. Naval Force Health Protection Program Review 2023 Presentation Slides. SAND2023-05198PE. Sandia National Lab.(SNL-NM), Albuquerque, NM (United States); 2023 Jun 26. link

  3. Livesu M, Pitzalis L, Cherchi G. Optimal dual schemes for adaptive grid based hexmeshing. ACM Transactions on Graphics (TOG). 2021 Dec 6;41(2):1-4. link

  4. Bracci M, Tarini M, Pietroni N, Livesu M, Cignoni P. HexaLab.net: An online viewer for hexahedral meshes. Computer-Aided Design. 2019 May 1;110:24-36. link