How do I get the centroid of my contact elements
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
-
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)
1 -
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)
1