How do I get the centroid of my contact elements

Aria
Aria Member, Employee Posts: 67
Ansys Employee Photogenic First Anniversary 25 Answers
✭✭✭✭

I want to save the centroid of the contact elements in all my contacts in a CSV. How would I do that in Mechanical?

Answers

  • Aria
    Aria Member, Employee Posts: 67
    Ansys Employee Photogenic First Anniversary 25 Answers
    ✭✭✭✭
    edited July 2023

    This is the best way I could come up with. Please keep in mind that contact elements are created on solve, meaning that before solve only the graphical representation of the contact exists. Therefore, the model must be solved and an RST in place in order for the script to work.

    import mech_dpf
    import Ans.DataProcessing as dpf
    mech_dpf.setExtAPI
    import units
    import csv
    import os 
    
    
    def get_matid(contact):
        solver_data = Model.Analyses[0].Solution.SolverData
        cont_data = solver_data.GetObjectData(contact)
        return cont_data.SourceId
     
     
    def get_mat_elems(contact, streams):
        mid = get_matid(contact)
        op = dpf.operators.scoping.on_property(
                                    property_name = "material",
                                    property_id = mid,
                                    requested_location = "Elemental",
                                    streams_container=streams)
        mat_elems = op.outputs.mesh_scoping.GetData().Ids
        return mat_elems
    
    
    def elem_to_nodes(elems, dataSource):
        model = dpf.Model(dataSource)
        nodes = []
        node_ids = [nodes.append(model.Mesh.ElementById(x).NodeIds) for x in elems]
        return nodes
    
    
    def nodal_coords(nodes):
        length_unit = ExtAPI.DataModel.Project.Model.Analyses[0].GeoData.Unit
        nodal_coords = [[Quantity(Model.Analyses[0].MeshData.NodeById(k).X, length_unit),
                        Quantity(Model.Analyses[0].MeshData.NodeById(k).Y, length_unit),
                        Quantity(Model.Analyses[0].MeshData.NodeById(k).Z, length_unit)] for k in nodes]
        return nodal_coords
    
    
    def elemental_centroid(elem_nodal_coords):
        unit = elem_nodal_coords[0][0].Unit
        points = [[x.Value for x in y] for y in elem_nodal_coords]
        x = [p[0] for p in points]
        y = [p[1] for p in points]
        z = [p[2] for p in points]
        centroid = [
            sum(x)/len(points), 
            sum(y)/len(points),
            sum(z)/len(points),
            unit]
        return centroid
    
    
    analysis1 = ExtAPI.DataModel.Project.Model.Analyses[0]
    dataSource = dpf.DataSources(analysis1.Solution.ResultFilePath)
    mech_dpf.setExtAPI(ExtAPI)
    streams = mech_dpf.GetStreams(0)
    
    contacts = DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion)
    contacts = [x for x in contacts if all([len(x.TargetLocation.Ids) > 0, len(x.SourceLocation.Ids) > 0, x.Suppressed == False])]
    conta_dict = {k.Name: get_mat_elems(k, streams) for k in contacts}
    
    conta_dict_resu = {}
    for key, val in conta_dict.iteritems():
        conta_elem = list(val)
        nodes = elem_to_nodes(conta_elem,dataSource)
        list_of_element_coords = [nodal_coords(node) for node in nodes]
        elem_centroids = [elemental_centroid(x) for x in list_of_element_coords]
    
    header = ["Contact name", "Element ID", "X", "Y", "Z", "unit"]
    path = r"C:\\test"
    file = "contact_element_centroid"
    if os.path.exists(path) == False:
        os.mkdir(path)
    filePath = os.path.join(path,file) + r".csv"
    with open(filePath, "wb") as f:
        writer = csv.writer(f)
        writer.writerow(header)
        for x,row in enumerate(elem_centroids):
            row.insert(0,conta_elem[x])
            row.insert(0,key)
            writer.writerow(row)
        
    ExtAPI.Log.WriteMessage("Result file was written to: " + filePath)
    
  • Aria
    Aria Member, Employee Posts: 67
    Ansys Employee Photogenic First Anniversary 25 Answers
    ✭✭✭✭
    edited July 2023

    Something similar could be achieved in Mechanical be retrieving the element/nodes associated with a geo face in Mechanical. As the contact elements are created on solve, the elements associated with the face will be the underlying solid elements if the contact faces are scoped between two solid objects.

    By comparing the corner node ID of each underlying element with the nodes associated with the geo face, we can figure what nodes are associated with surface element segment.

    conta = DataModel.GetObjectsByType(DataModelObjectCategory.ContactRegion)[0]
    faceId = conta.SourceLocation.Ids[0]
    meshData = ExtAPI.DataModel.Project.Model.Analyses[0].MeshData # reference meshData
    faceMesh = meshData.MeshRegionById(faceId) # get mesh data for face
    contactSurfaceNodes = set(faceMesh.NodeIds)
    header = ["element id", "node id", "x", "y", "z"]
    row = [header]
    for element in faceMesh.ElementIds:
        elementObject = meshData.ElementById(element)
        for cornerNodeId in elementObject.CornerNodeIds:
            if cornerNodeId in contactSurfaceNodes:
                nodeObj = meshData.NodeById(cornerNodeId)
                row.append([element, cornerNodeId, nodeObj.X, nodeObj.Y, nodeObj.Z])
    
    
    path = r"C:\\test"
    file = "mechanical_method"
    if os.path.exists(path) == False:
        os.mkdir(path)
    filePath = os.path.join(path,file) + r".csv"
    with open(filePath, "wb") as f:
        writer = csv.writer(f)
        writer.writerows(row)