How do I get element beneath the selected Hex element in a mesh using PyDPF?

Ayush Kumar
Ayush Kumar Member, Moderator, Employee Posts: 456
100 Answers 250 Likes 100 Comments Second Anniversary
✭✭✭✭

How do I get element beneath the selected Hex element in a mesh using PyDPF?

Tagged:

Comments

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 456
    100 Answers 250 Likes 100 Comments Second Anniversary
    ✭✭✭✭

    The methodology used is:

    1. Get the normal and centroid of the selected element.
    2. Generate a 3D line passing through the centroid and along the normal.
    3. Get centroids of all the neighboring elements.
    4. Filter out the centroid with the smallest distance to the 3D line.
    5. Fetch the corresponding element ID to the centroid in step 4.

    Below is the Python code using PyDPF for the above steps:

     import numpy as np
    from ansys.dpf import core as dpf
    
    rst_path = r"\Path\to\file.rst"
    ds = dpf.DataSources(rst_path)
    
    model = dpf.Model(rst_path)
    mesh = model.metadata.meshed_region
    
    # Replace EID of the selected element
    eid = 1959
    
    ms_eid = dpf.Scoping()
    ms_eid.ids = [eid]
    
    # Get Nodal scoping
    ns = dpf.Scoping()
    ns.ids = mesh.elements.element_by_id(eid).node_ids
    
    # Get neighbouring elements
    es = dpf.operators.scoping.transpose(
        mesh_scoping=ns,
        meshed_region=mesh,
        inclusive=1,
        requested_location=dpf.locations.elemental
    )
    es_scoping = es.outputs.mesh_scoping_as_scoping.get_data()
    
    # Get normal on the element of interest
    normals_op = dpf.operators.geo.normals(mesh=mesh, mesh_scoping=ms_eid)
    normals = normals_op.outputs.field.get_data().data
    print(normals)
    
    # Get element centroids
    ec = model.operator("centroids")
    ec_f = ec.outputs.fields_container.get_data()[0]
    point_start = ec_f.get_entity_data_by_id(eid)
    ec_res_field = dpf.operators.scoping.rescope(
        fields=ec_f, mesh_scoping=es_scoping).outputs.fields_as_field.get_data()
    ec_res = ec_res_field.data
    
    
    def distance_to_line(A, B, C):
        # Calculate the distance of point C from the line AB
        n = B - A
        v = C - A
        distance = np.linalg.norm(np.cross(n, v)) / np.linalg.norm(n)
        return distance
    
    
    def find_nearest_points_along_line(points, start, direction):
        # Convert the line to a vector
        line_vec = direction / np.linalg.norm(direction)
    
        # Calculate distances for each point
        distances = []
        for point in points:
            d = distance_to_line(start, start + line_vec, point)
            distances.append(d)
    
        # Sort points by distance
        sorted_indices = np.argsort(distances)
        nearest_indices = sorted_indices[:3]
    
        return nearest_indices
    
    
    # Get indices of points nearest to the normal
    nearest_indices = find_nearest_points_along_line(ec_res, point_start, normals)
    
    # Element beneath
    second_closest_index = nearest_indices[1]
    
    eid_res = ec_res_field.scoping.ids[second_closest_index]
    print(f"Element closest to centroid of Element {eid} is {eid_res}")