簡體   English   中英

提取平均值使用 python 來自 odb 文件和節點集的節點應力

[英]Extracting avg. nodal stresses from odb file and nodeset using python

我想做什么:

  • 我想提取已轉換為局部坐標系的節點位移 (U2) 和應力 (S22),以便在給定分析步驟的每一幀中為它們的變化設置動畫。
  • 提取歷史輸出和節點位移場是可以的。 然而,獲得壓力似乎更麻煩。

Animation

問題:

  • NODAL 指定的應力場不是節點平均的。 我如何獲得這些?
  • 節點應力 output 似乎有點隨機,即使它已通過 subsetregion = nodeSet 指定。 看起來我只訪問了沿我定義的路徑節點集的一半非平均節點應力。

我已經發布了整個腳本,但出錯的地方在於步驟中的幀循環:for frameNo in range(0,nFrames): 任何輸入或想法將不勝感激。

    odb = openOdb(path = "PostJob.odb")



  partName = odb.rootAssembly.instances.keys()
    
    print('AVAILABLE PARTS AND PART NAMES IN THE MODEL', partName)
    
    nSets = len(odb.rootAssembly.instances[partName[0]].nodeSets.keys())
    nSetKeys = odb.rootAssembly.instances[partName[0]].nodeSets.keys()

    print('AVAILABLE SETS IN THE PART ',partName[0],'sets',nSetKeys)
    print('NO. OF SETS IN PART INSTANCE',nSets)
    
    # ------------------------------------------------------------------------
    # FORCE-DISPLACEMENT CURVES ----------------------------------------------
    # ------------------------------------------------------------------------
    
    # Extract U1 and RF1 from the history output
    U1data  = odb.steps['CZ Analysis'].historyRegions['Node ASSEMBLY.1'].historyOutputs['U1'].data
    RF1data = odb.steps['CZ Analysis'].historyRegions['Node ASSEMBLY.1'].historyOutputs['RF1'].data
    
    
    # The data is in the form of tuples, which we will convert to np. arrays instead.
    U1data=np.asarray(U1data)
    RF1data = np.array(RF1data)

    # Plotting the force-displacement curve
    plt.plot(U1data[:,1],RF1data[:,1])
    
    plt.ylabel('Force: RF1 in [N]')
    plt.xlabel('Displacement: U1 in [mm]')
    plt.xlim((0,2))
    plt.title('Force-Displacement Curve')
    
    #plt.show()
 
    # ------------------------------------------------------------------------
    # INTERFACE TRACTIONS ----------------------------------------------------
    # ------------------------------------------------------------------------
    
    # Access the test node path and create a node path in the visulalization module
    
    alpha = 10.0*math.pi/180 # with X-axis
    
    # Perform a coordinate transformation on the nodal coordinates by using the transformation matrix T
    R = np.array([[math.cos(alpha),-math.sin(alpha),0],
                  [math.sin(alpha), math.cos(alpha),0],
                  [              0,               0,1]])
    # T = [cos alpha, -sin alpha, 0; sin alpha, cos alpha, 0; 0, 0, 1] 
    print(R)
    
    e1 = np.array([1,0,0])
    e2 = np.array([0,1,0])
    e3 = np.array([0,0,1])
    
    e1p = np.dot(R, e1.transpose())
    e2p = np.dot(R, e2.transpose())
    e3p = np.dot(R, e3.transpose())
    
    
    origin=[0,0,0]
    
    #plt.figure()
    origin = np.array([0, 0, 0]) 
    #plt.quiver([e1p[0],e2p[0],e3p[0]],[e1p[1],e2p[1],e3p[1]], color=['r','g','b'],scale=21)
   
    # Create a new coordinate system
    coordSys = odb.rootAssembly.DatumCsysByThreePoints(name='Bond-CSYS', coordSysType=CARTESIAN, 
                                                        origin=(0.0,0.0,0.0), 
                                                        point1=tuple(e1p),
                                                        point2=tuple(e2p))
    
    # Extract the node set and stress field of the node path.
    instance = odb.rootAssembly.instances['ADHESIVE']
    
    bondPath = instance.nodeSets['MIDNODESET']
     
    allBondPathNodes = bondPath.nodes[0:-1]
    
    nNodes = len(bondPath.nodes)
    
    print('NUMBER OF NODES IN BONDLINE PATH FOUND FROM MIDNODESET', nNodes)
    
    nodeCoord = np.zeros([3,nNodes])


    
    # Transform the coordinates into the local coordinates of the bondline
    jj = -1
    for node in allBondPathNodes:
        jj += 1
        nodeCoord[0,jj] = node.coordinates[0]
        nodeCoord[1,jj] = node.coordinates[1]
        nodeCoord[2,jj] = node.coordinates[2]

    # plt.figure()
    # plt.plot(nodeCoord[0,:],nodeCoord[1,:])


    # Transform the coordinates and determine the 
    transNodeCoord = np.dot(np.linalg.inv(R),nodeCoord)

    # Test coordinates by plotting the line
    #plt.plot(transNodeCoord[0,:],transNodeCoord[1,:])
    
    
    # EXTRACT RELEVANT FIELDS ------
    
    # Create a for loop to loop over the number of frames in the odb:

    
    step  = odb.steps['CZ Analysis']
    
    nFrames = len(step.frames)
    
    print("No. of Frames", nFrames)
    
    # Initialize arrays outside for loop
    U11  = np.zeros([nNodes,nFrames])
    U22  = np.zeros([nNodes,nFrames])
    t11  = np.zeros([nNodes,nFrames])
    t22  = np.zeros([nNodes,nFrames])
    t12  = np.zeros([nNodes,nFrames])

    for frameNo in range(0,nFrames):
    
        # Current frame no in analysis step 'CZ Analysis'
        frame = step.frames[frameNo]
    
        # Get the stress and displacement field for the current frame
        stressField = frame.fieldOutputs['S']
        displacement = frame.fieldOutputs['U']
        
        # Transform the displacement and stress field to local coordinate system
        transfStressField = stressField.getTransformedField(datumCsys=coordSys)
        transfDisplacementField = displacement.getTransformedField(datumCsys = coordSys)
        
        # Extract nodal field results for subset region = bondPath
        pathStressField = transfStressField.getSubset(region=bondPath,position=NODAL)
        pathDisplacementField = transfDisplacementField.getSubset(region=bondPath)
        
        # Extract displacement field U1 component
        dispU1   = pathDisplacementField.getScalarField(componentLabel='U1')
        dispU2   = pathDisplacementField.getScalarField(componentLabel='U2')

        # Loop over nodal values and append them to np.array
        jj = -1

        for u,v, stress in zip(dispU1.values, dispU2.values,transfStressField.values):
            jj += 1
            
            U11[jj][frameNo]  = u.data
            U22[jj][frameNo]  = v.data
            t11[jj][frameNo]  = stress.data[0]
            t22[jj][frameNo]  = stress.data[1]
            t12[jj][frameNo]  = stress.data[3]
            #print('Displacement node label', u.nodeLabel,v.nodeLabel,'Stress object node label', stress.nodeLabel)
            #print("Node Label", v.nodeLabel, "Displacement Value", v.data,"S11",stress.data[0], "S22",stress.data[1],"S12",stress.data[3])
        
        #print('POSITION: ', v.position, "Coordinate", node.coordinates, "Displacement Value", v.data)
        
    
    fig, axs = plt.subplots(2)
    axs[1].set_xlabel('x-coordinate')

    
    def animate(i):
        axs[0].clear()
        axs[1].clear()
        #ax.plot(transNodeCoord[0,:],t22[:,i]) # stresses are discontinous because they are specified at nodes
        #ax.set_title('Displacement: U2', 'Frame No:',i)
        axs[0].set_title('Displacement: U2 , Frame No: {}'.format(i))
        axs[0].plot(np.flip(transNodeCoord[0,:]),U22[:,i])  # Displacements are continous, but look weird.-
        axs[1].set_title('Traction: T22 , Frame No: {}'.format(i))
        axs[1].plot(np.flip(transNodeCoord[0,:]),t22[:,i])
        #ax.set_xlim([0,transNodeCoord[-1,:]])
    
    
    # Create animation
    
    ani1 = FuncAnimation(fig,animate,frames=32,interval=500,blit=False,repeat=True)
    np.set_printoptions(threshold=np.inf)

Abaqus 計算位於 3D 單元內部的積分點處的應力(數字和 position 取決於單元類型)。 計算出應力后,它會外推到單元的節點。

因此,每個節點將從共享該節點的每個元素中獲取一個值。 如果網格划分不夠精細,這樣的插值可能會導致從相鄰元素獲得的節點值存在很大差異。 出於可視化目的,Abaqus 默認對這些值取平均值

對於您的任務,您可以導出節點處的值並自行執行平均。 或者使用在元素質心/積分點處獲得的結果,並將這些值與相應的坐標配對。 在獲得應力與 X 坐標和應變與 X 坐標數據集后,您可以先插入或插入第二個,以便兩者的 X 坐標匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM