View Issue Details

IDProjectCategoryView StatusLast Update
0004191OpenFOAMBugpublic2024-12-18 08:07
Reporterdemichie Assigned Tohenry  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionsuspended 
PlatformGNU/LinuxOSOtherOS Version(please specify)
Product Version12 
Summary0004191: non-orthogonality after refineMesh
DescriptionAfter refineMesh with a pure heaxahedral mesh, generated by blockMesh, the maximum non-orthogonality increases a lot. This is due to the way new points are computed. For a face, the middle-points on the edges and the centroid of the face can be mis-aligned, creating the non orthogonality problem. This thing happens also in the case of flat faces (flatness=1). I'm attaching 3 images and a Python script which highlights this behavior:
1) zigzag_orig.png a crinkle slice of the original mesh before refineMesh, where a cell producing this problem is highlighted;
2) zigzag.png the refined mesh, where it is possible to see the zigzag behaviour created by refineMesh, which at the end results in increased non-orthogonality between the new smaller cells
3) Figure_1.pdf the points for the face highlighted in the previous figures, computed by the Python script (I checked and the new points have the same coordinates of those generated by refineMesh. The green point is the centroid, which is poorly aligned with the edge midpoints, producing the non-orthogonality.
4) checkRefine.py a Python script to create the previous plot. in the attached version the coordinates used for the previous figures are commented, while different coordinates for a flat face are used. This shows that the problem occurs also with perfectly flat faces.

The effect is produced by the way the face centroid is computed, which takes into account the areas of the triangles obtained connecting the mean of the vertices with the sides of the face. A relatively small difference in the length of two opposite sides, for a face with a relatively large aspect ratio, produce significant differences in the areas, and thus moves the centroid toward the larger of the two opposite sides of the face. For the middle points of the edges we don't have this shift associated with the areas, and it would be difficult to imagine how to do this thing, because each edge belongs to two faces. So, the only way to improve the non-orthogonality could be, only for the refinement, to use the average of the vertices (black point in Figure_1.pdf) instead of the centroid.
TagsNo tags attached.

Activities

demichie

2024-12-18 07:45

reporter  

checkRefine.py (5,182 bytes)   
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def calculate_face_center(face_points):
    """
    Compute the geometric center (centroid) of a possibly non-planar face.
    Args:
        face_points (list of list): List of points defining the face.
                                    Each point is a 3D list [x, y, z].
    Returns:
        np.array: The computed face center as a 3D vector.
    """
    points = np.array(face_points)
    p_avg = np.mean(points, axis=0)  # Step 1: Geometric average of vertices

    sumA = np.zeros(3)
    N = len(points)
    for i in range(N):
        p = points[i]
        p_next = points[(i + 1) % N]  # Wrap around for last vertex
        sumA += np.cross(p_next - p, p_avg - p)  # Step 2: Area normal sum

    sumA_norm = np.linalg.norm(sumA)
    if sumA_norm == 0:
        raise ValueError("Degenerate face: area normal is zero.")
    sumA_hat = sumA / sumA_norm  # Step 3: Normalize area normal

    sumAn = 0.0
    sumAnc = np.zeros(3)
    for i in range(N):
        p = points[i]
        p_next = points[(i + 1) % N]
        a = np.cross(p_next - p, p_avg - p)
        c = (p + p_next + p_avg) / 3.0  # Triangle center
        an = np.dot(a, sumA_hat)  # Projected area
        print(p,p_next,p_avg)
        print(np.linalg.norm(a),an)
        sumAn += an
        sumAnc += an * c

    face_center = sumAnc / sumAn  # Final centroid
    return face_center

def compute_edge_midpoints(face_points):
    """
    Compute the midpoints of the edges of a face.
    Args:
        face_points (list of list): List of points defining the face.
    Returns:
        list of np.array: List of midpoints for each edge.
    """
    points = np.array(face_points)
    midpoints = []
    N = len(points)
    for i in range(N):
        p = points[i]
        p_next = points[(i + 1) % N]
        midpoint = (p + p_next) / 2.0
        midpoints.append(midpoint)
    return midpoints

def set_axes_equal(ax):
    """
    Set equal scaling for all axes in a 3D plot.
    This ensures that the x, y, and z axes have the same scale.
    """
    limits = np.array([
        ax.get_xlim3d(),
        ax.get_ylim3d(),
        ax.get_zlim3d(),
    ])
    span = limits[:, 1] - limits[:, 0]
    center = np.mean(limits, axis=1)
    radius = 0.5 * max(span)
    
    ax.set_xlim3d([center[0] - radius, center[0] + radius])
    ax.set_ylim3d([center[1] - radius, center[1] + radius])
    ax.set_zlim3d([center[2] - radius, center[2] + radius])


def plot_face_with_centroid_and_midpoints(face_points):
    """
    Plot a 3D face, its centroid, edge midpoints, and lines connecting midpoints to the centroid.
    Args:
        face_points (list of list): List of points defining the face.
    """
    face_points = np.array(face_points)  # Ensure points are a NumPy array

    p_avg = np.mean(face_points, axis=0)  # Step 1: Geometric average of vertices
    print(p_avg)

    face_center = calculate_face_center(face_points)
    edge_midpoints = compute_edge_midpoints(face_points)

    # Extract face edges and vertices for plotting
    x = np.append(face_points[:, 0], face_points[0, 0])  # Close the face loop
    y = np.append(face_points[:, 1], face_points[0, 1])
    z = np.append(face_points[:, 2], face_points[0, 2])

    # Initialize 3D plot
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    # Plot the face edges
    ax.plot(x, y, z, color='blue', linewidth=2, label='Face Edges')

    # Plot the face edges
    ax.scatter(p_avg[0],p_avg[1],p_avg[2],color='black', s=30, label='p_avg')


    # Plot the face vertices
    ax.scatter(face_points[:, 0], face_points[:, 1], face_points[:, 2],
               color='red', s=50, label='Face Vertices')

    # Plot the computed centroid
    ax.scatter(face_center[0], face_center[1], face_center[2],
               color='green', s=100, label='Face Center')

    # Plot the midpoints of edges
    edge_midpoints = np.array(edge_midpoints)
    ax.scatter(edge_midpoints[:, 0], edge_midpoints[:, 1], edge_midpoints[:, 2],
               color='cyan', s=75, label='Edge Midpoints')

    # Plot lines connecting edge midpoints to the centroid
    for midpoint in edge_midpoints:
        ax.plot([midpoint[0], face_center[0]],
                [midpoint[1], face_center[1]],
                [midpoint[2], face_center[2]],
                color='purple', linestyle='--', linewidth=1)

    # Set equal scaling for all axes
    set_axes_equal(ax)

    # Set plot labels and title
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    ax.set_title('3D Face with Centroid and Edge Midpoints')

    # Add a legend
    ax.legend()

    # Show the plot
    plt.show()

if __name__ == "__main__":
    # Example: Define a quadrilateral face with slight non-planarity
    face_points = [
        [0.0, 0.0, 0.0],
        [0.0,  0.5, 0.0],
        [10.0, 0.6, 0.0],
        [10.0, -0.1, 0.0]
#        [-1365.22, 361.362, 181.82],
#        [-1366.40,  361.782, 180.357],
#        [-1350.43, 361.919, 165.43],
#        [-1348.90, 361.541, 167.321]
    ]

    # Call the plotting function
    plot_face_with_centroid_and_midpoints(face_points)

checkRefine.py (5,182 bytes)   
zigzag_orig.png (678,271 bytes)
zigzag.png (797,648 bytes)
Figure_1.pdf (18,735 bytes)

henry

2024-12-18 08:07

manager   ~0013489

Development request requiring funding.

Issue History

Date Modified Username Field Change
2024-12-18 07:45 demichie New Issue
2024-12-18 07:45 demichie File Added: checkRefine.py
2024-12-18 07:45 demichie File Added: zigzag_orig.png
2024-12-18 07:45 demichie File Added: zigzag.png
2024-12-18 07:45 demichie File Added: Figure_1.pdf
2024-12-18 08:07 henry Assigned To => henry
2024-12-18 08:07 henry Status new => closed
2024-12-18 08:07 henry Resolution open => suspended
2024-12-18 08:07 henry Note Added: 0013489