How do I convert LS-Dyna results to USD format?
Ayush Kumar
Member, Moderator, Employee Posts: 472
✭✭✭✭
Comments
-
This example converts a Shell Model to USD format and stores some results at several time-steps as Attributes for the Primitive "/d3plot"
Tested with:
- usd-core version 23.11
- Python version 3.10.10
- ansys-dpf-core 0.10.0
- from pxr import Sdf, Usd, UsdGeom
- from ansys.dpf import core as dpf
- timescopingToken = "ansys:lsdyna:timescoping"
- nodeIndicesToken = "ansys:lsdyna:nodeindices"
- attributesTokens = ["ansys:lsdyna:acceleration", "ansys:lsdyna:displacement", "ansys:lsdyna:stress",
- "ansys:lsdyna:velocity"]
- globalFieldTokenK = ["ansys:lsdyna:global_k", "ansys:lsdyna:global_k_time"]
- globalFieldTokenU = ["ansys:lsdyna:global_u", "ansys:lsdyna:global_u_time"]
- globalFieldTokenH = ["ansys:lsdyna:global_h", "ansys:lsdyna:global_h_time"]
- globalFieldTokenV = ["ansys:lsdyna:global_v", "ansys:lsdyna:global_v_time"]
- descriptionToken = "ansy:dpf:description"
- fieldTypeToken = "ansys:dpf:selectedFieldType"
- nbFramesPerTimestep = 5
- # create mesh from a d3plot file
- def create_dpf_prim_with_stage(filepath: str, primname: str, stage):
- # loads the data
- print("Loading model " + filepath)
- ds = dpf.DataSources()
- ds.set_result_file_path(filepath, "d3plot") # Result file
- # Instantiate Model Class
- model = dpf.Model(ds)
- nbResults = model.metadata.time_freq_support.n_sets
- timeScoping = []
- for ts in range(nbResults):
- timeScoping.append(ts)
- # Whole mesh
- mesh = model.metadata.meshed_region
- # Extract skin mesh
- op = dpf.operators.mesh.skin(mesh=mesh)
- skin_mesh = op.outputs.mesh.get_data()
- # Extract Coordinates results
- coord = model.results.coordinates(time_scoping=timeScoping)
- coord_fc = coord.outputs.fields_container.get_data()
- # Extract Acceleration results
- accel = model.results.acceleration(time_scoping=timeScoping)
- accel_fc = accel.outputs.fields_container.get_data()
- # Extract Displacement results
- disp = model.results.displacement(time_scoping=timeScoping)
- disp_fc = disp.outputs.fields_container.get_data()
- # Extract Stress results
- stress = model.results.stress(time_scoping=timeScoping)
- stress_fc = stress.outputs.fields_container.get_data()
- # Extract Velocity results
- vel = model.results.velocity(time_scoping=timeScoping)
- vel_fc = vel.outputs.fields_container.get_data()
- # globals
- K = model.results.global_kinetic_energy.eval()
- U = model.results.global_internal_energy().eval()
- H = model.results.global_total_energy().eval()
- V = model.results.global_velocity().eval()
- # add info to the current stage
- usd_mesh = UsdGeom.Mesh.Define(stage, primname)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenK[0], Sdf.ValueTypeNames.FloatArray).Set(K[0].data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenU[0], Sdf.ValueTypeNames.FloatArray).Set(U[0].data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenH[0], Sdf.ValueTypeNames.FloatArray).Set(H[0].data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenV[0], Sdf.ValueTypeNames.FloatArray).Set(V[0].data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenK[1], Sdf.ValueTypeNames.FloatArray).Set(
- K.time_freq_support.time_frequencies.data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenU[1], Sdf.ValueTypeNames.FloatArray).Set(
- U.time_freq_support.time_frequencies.data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenH[1], Sdf.ValueTypeNames.FloatArray).Set(
- H.time_freq_support.time_frequencies.data)
- usd_mesh.GetPrim().CreateAttribute(globalFieldTokenV[1], Sdf.ValueTypeNames.FloatArray).Set(
- V.time_freq_support.time_frequencies.data)
- # add number of timesteps as an attribute
- usd_mesh.GetPrim().CreateAttribute(timescopingToken, Sdf.ValueTypeNames.IntArray).Set(timeScoping)
- """indices, faceCount and nodeIndices doesn't change overtime."""
- nbElements = len(mesh.elements)
- indices = []
- faceCounts = []
- nodeIndices = []
- # fills vertices, indices and face counts
- for elementId in range(nbElements):
- element = mesh.elements[elementId]
- # face represents a triangle or quad
- faceCounts.append(len(element.nodes))
- # adds vertex coordinates
- for node in element.nodes:
- nodeIndices.append(node.index)
- # add indices
- indices.append(len(indices))
- # Create Indices
- usd_mesh.GetFaceVertexIndicesAttr().Set(indices)
- # Face counts (3 for tris, 4 for quads...)
- usd_mesh.GetFaceVertexCountsAttr().Set(faceCounts)
- # Node indoces for further field access
- usd_mesh.GetPrim().CreateAttribute(nodeIndicesToken, Sdf.ValueTypeNames.IntArray).Set(nodeIndices)
- # descriptions
- usd_mesh.GetPrim().CreateAttribute(descriptionToken, Sdf.ValueTypeNames.String).Set(
- model.metadata.result_info.__str__())
- # Go through all the timesteps
- for i in range(nbResults):
- print("Importing timecode " + str(i) + "/" + str(nbResults))
- # Create the current timecode
- timeCode = Usd.TimeCode(float(i * nbFramesPerTimestep))
- # set custom attributes in the USD
- usd_mesh.GetPrim().CreateAttribute(attributesTokens[0], Sdf.ValueTypeNames.Float3Array).Set(accel_fc[i].data,
- timeCode)
- usd_mesh.GetPrim().CreateAttribute(attributesTokens[1], Sdf.ValueTypeNames.Float3Array).Set(disp_fc[i].data,
- timeCode)
- usd_mesh.GetPrim().CreateAttribute(attributesTokens[2], Sdf.ValueTypeNames.Float3Array).Set(stress_fc[i].data,
- timeCode)
- usd_mesh.GetPrim().CreateAttribute(attributesTokens[3], Sdf.ValueTypeNames.Float3Array).Set(vel_fc[i].data,
- timeCode)
- # Fill vertices, indices and faces arrays
- vertices = []
- # fills vertices
- curCoord = coord_fc[i].data
- for nodeIdx in nodeIndices:
- vertices.append(curCoord[nodeIdx])
- # Create vertices
- usd_mesh.GetPointsAttr().Set(vertices, timeCode)
- def export():
- # create a new stage
- stage = Usd.Stage.CreateInMemory('dpf_dyna_ov.usd')
- # convert
- create_dpf_prim_with_stage(r"\LS-DYNA\RESULTS\PATH\d3plot", "/d3plot", stage)
- # save the stage in the end
- stage.GetRootLayer().Export(r"\Output\path\dpf_dyna_ov.usda")
- # Entry point
- if __name__ == '__main__':
- export()
2