How do I convert LS-Dyna results to USD format?

Ayush Kumar
Ayush Kumar Member, Moderator, Employee Posts: 444
250 Likes Solution Developer Community of Practice Member Ansys Employee First Anniversary
✭✭✭✭
edited November 2023 in Structures

How do I convert LS-Dyna results to USD format?

Tagged:

Comments

  • Ayush Kumar
    Ayush Kumar Member, Moderator, Employee Posts: 444
    250 Likes Solution Developer Community of Practice Member Ansys Employee First Anniversary
    ✭✭✭✭
    edited November 2023

    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:

    1. usd-core version 23.11
    2. Python version 3.10.10
    3. 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()