def ErrorNorm_CompressionBar(): """ Calculate and print the error norm (L2 and energy norm) of the elastic bar under compression for convergence study """ ngp = 3 [w, gp] = gauss(ngp) # extract Gauss points and weights L2Norm = 0 EnNorm = 0 L2NormEx = 0 EnNormEx = 0 for e in range(model.nel): de = model.d[model.LM[:, e] - 1] # extract element nodal displacements IENe = model.IEN[:, e] - 1 # extract local connectivity information xe = model.x[IENe] # extract element x coordinates J = (xe[-1] - xe[0]) / 2 # compute Jacobian for i in range(ngp): xt = 0.5 * (xe[0] + xe[-1] ) + J * gp[i] # Gauss points in physical coordinates N = Nmatrix1D(xt, xe) # shape functions matrix B = Bmatrix1D(xt, xe) # derivative of shape functions matrix Ee = N @ model.E[IENe] # Young's modulus at element gauss points uh = N @ de # displacement at gauss point uex = (-xt**3 / 6 + xt) / Ee # Exact displacement L2Norm += J * w[i] * (uex - uh)**2 L2NormEx += J * w[i] * (uex)**2 sh = B @ de # strain at Gauss points sex = (-xt**2 / 2 + 1) / Ee # Exact strain EnNorm += 0.5 * J * w[i] * Ee * (sex - sh)**2 EnNormEx += 0.5 * J * w[i] * Ee * (sex)**2 L2Norm = sqrt(L2Norm) L2NormEx = sqrt(L2NormEx) EnNorm = sqrt(EnNorm) EnNormEx = sqrt(EnNormEx) # print stresses at element gauss points print('\nError norms') print('%13s %13s %13s %13s %13s' % ('h', 'L2Norm', 'L2NormRel', 'EnNorm', 'EnNormRel')) print( '%13.6E %13.6E %13.6E %13.6E %13.6E\n' % (2 / model.nel, L2Norm, L2Norm / L2NormEx, EnNorm, EnNorm / EnNormEx)) return 2 / model.nel, L2Norm, EnNorm
def disp_and_stress(e, d, ax1, ax2): """ Print stresses at Gauss points, plot displacements and stress distributions obtained by FE analysiss Args: e : (int) element number d : (numnp.array(neq,1)) solution vector ax1 : axis to draw displacement distribution ax2 : axis to draw stress distribution """ de = model.d[model.LM[:, e] - 1] # extract element nodal displacements IENe = model.IEN[:, e] - 1 # extract element connectivity information xe = model.x[IENe] # extract element coordinates J = (xe[-1] - xe[0]) / 2 # Jacobian w, gp = gauss(model.ngp) # Gauss points and weights # compute stresses at Gauss points gauss_pt = np.zeros(model.ngp) stress_gauss = np.zeros(model.ngp) for i in range(model.ngp): xt = 0.5 * (xe[0] + xe[-1] ) + J * gp[i] # Gauss point in the physical coordinates gauss_pt[i] = xt # store gauss point information N = Nmatrix1D(xt, xe) # extract shape functions B = Bmatrix1D(xt, xe) # extract derivative of shape functions Ee = N @ model.E[IENe] # Young's modulus at element Gauss points stress_gauss[i] = Ee * B @ de # compute stresses at Gauss points # print stresses at element gauss points print("%8d %12.6f %12.6f %16.6f %16.6f" % (e, gauss_pt[0], gauss_pt[1], stress_gauss[0], stress_gauss[1])) # equally distributed coordinate within an element xplot = np.linspace(xe[0], xe[-1], model.nplot) # compute displacements and stresses displacement = np.zeros(model.nplot) stress = np.zeros(model.nplot) for i in range(model.nplot): xi = xplot[i] # current coordinate N = Nmatrix1D(xi, xe) # shape functions B = Bmatrix1D(xi, xe) # derivative of shape functions Ee = N @ model.E[IENe] # Young's modulus displacement[i] = N @ de # displacement output stress[i] = Ee * B @ de # stress output s # plot displacements and stresses line1, = ax1.plot(xplot, displacement) line2, = ax2.plot(xplot, stress) if e == 0: line1.set_label('FE') line2.set_label('FE')
def BarElem(e): """ Calculate element stiffness matrix and element nodal body force vector Args: e : (int) element number Returns: ke, fe ke : (numpy(nen,nen)) element stiffness matrix fe : (numpy(nen,1)) element nodal force vector """ IENe = model.IEN[:, e] - 1 # extract local connectivity information xe = model.x[IENe] # extract element x coordinates J = (xe[model.nen - 1] - xe[0]) / 2 # compute Jacobian [w, gp] = gauss(model.ngp) # extract Gauss points and weights ke = np.zeros( (model.nen, model.nen)) # initialize element stiffness matrix fe = np.zeros((model.nen, 1)) # initialize element nodal force vector for i in range(model.ngp): # Compute Gauss points in physical coordinates xt = 0.5 * (xe[0] + xe[-1]) + J * gp[i] # Calculate the element shape function matrix and its derivative N = Nmatrix1D(xt, xe) B = Bmatrix1D(xt, xe) # cross-sectional area,Young's modulus and body force at gauss points Ae = N @ model.CArea[IENe] Ee = N @ model.E[IENe] be = N @ model.body[IENe] # compute element stiffness matrix and nodal body force vector ke = ke + w[i] * Ae * Ee * (B.T @ B) fe = fe + w[i] * N.T * be ke = J * ke fe = J * fe # check for point forces in this element for i in range(model.np): # loop over all point forces Pi = model.P[i] # extract point force xpi = model.xp[ i] # extract the location of point force within an element if xe[0] <= xpi < xe[-1]: # add to the nodal force vector fe = fe + Pi * np.transpose(Nmatrix1D(xpi, xe)) return ke, fe
def point_and_trac(): """ Add the nodal forces and natural B.C. to the global force vector. """ # Assemble point forces model.f = model.f + model.P[model.ID - 1] # Compute nodal boundary force vector for i in range(model.nbe): ft = np.zeros((4, 1)) # initialize nodal boundary force vector node1 = int(model.n_bc[0, i]) # first node node2 = int(model.n_bc[1, i]) # second node n_bce = model.n_bc[2:, i].reshape((-1, 1)) # traction value at node1 # coordinates x1 = model.x[node1 - 1] y1 = model.y[node1 - 1] x2 = model.x[node2 - 1] y2 = model.y[node2 - 1] # edge length leng = np.sqrt((x2 - x1)**2 + (y2 - y1)**2) J = leng/2.0 w, gp = gauss(model.ngp) for j in range(model.ngp): psi = gp[j] N = 0.5*np.array([[1-psi, 0, 1+psi, 0], [0, 1-psi, 0, 1+psi]]) traction = N@n_bce ft = ft + w[j]*J*(N.T@traction) # Assemble nodal boundary force vector ind1 = model.ndof*(node1 - 1) ind2 = model.ndof*(node2 - 1) model.f[model.ID[ind1] - 1, 0] += ft[0] model.f[model.ID[ind1 + 1] - 1, 0] += ft[1] model.f[model.ID[ind2] - 1, 0] += ft[2] model.f[model.ID[ind2 + 1] - 1, 0] += ft[3]
def get_stress(e): """ Print the element stress on Gauss Point. Args: e : The element number """ de = model.d[model.LM[:, e] - 1] # extract element nodal displacements # get coordinates of element nodes je = model.IEN[:, e] - 1 C = np.array([model.x[je], model.y[je]]).T # get gauss points and weights w, gp = gauss(model.ngp) # compute strains and stress at the gauss points ind = 0 number_gp = model.ngp*model.ngp X = np.zeros((number_gp, 2)) strain = np.zeros((3, number_gp)) stress = np.zeros((3, number_gp)) for i in range(model.ngp): for j in range(model.ngp): eta = gp[i] psi = gp[j] # shape functions matrix N = NmatElast2D(eta, psi) # derivative of the shape functions B, detJ = BmatElast2D(eta, psi, C) Na = np.array([N[0, 0], N[0, 2], N[0, 4], N[0, 6]]) X[ind, :] = Na@C strain[:, ind] = (B@de).T.squeeze() stress[:, ind] = (model.D@(strain[:, ind].reshape((-1, 1)))).T.squeeze() ind += 1 print("\tx-coord\t\t\ty-coord\t\t\ts_xx\t\t\ts_yy\t\t\ts_xy") for i in range(number_gp): print("\t{}\t\t{}\t\t{}\t\t{}\t\t{}".format(X[i, 0], X[i, 1], stress[0, i], stress[1, i], stress[2, i]))
def Elast2DElem(e): """ Calculate element stiffness matrix and element nodal body force vector Args: e : (int) element number Returns: ke, fe ke : (numpy(nen,nen)) element stiffness matrix fe : (numpy(nen,1)) element nodal force vector """ ke = np.zeros((model.nen * model.ndof, model.nen * model.ndof)) fe = np.zeros((model.nen * model.ndof, 1)) # get coordinates of element nodes je = model.IEN[:, e] - 1 C = np.array([model.x[je], model.y[je]]).T # get gauss points and weights w, gp = gauss(model.ngp) # compute element stiffness matrix and element nodal force vector for i in range(model.ngp): for j in range(model.ngp): eta = gp[i] psi = gp[j] # shape functions matrix N = NmatElast2D(eta, psi) # derivative of the shape functions B, detJ = BmatElast2D(eta, psi, C) # element stiffness matrix ke = ke + w[i] * w[j] * detJ * (B.T @ model.D @ B) be = N @ (model.b[:, e].reshape((-1, 1))) fe = fe + w[i] * w[j] * detJ * (N.T @ be) return ke, fe
def ErrorNorm_ConcentratedForce(flag): """ Calculate and print the error norm (L2 and energy norm) of the elastic bar under concentrated force and body force for convergence study Args: flag: (bool) whether x0 = 15*l/16 is the node or not """ ngp = 3 [w, gp] = gauss(ngp) # extract Gauss points and weights E = 10000.0 A = 1.0 l = 16.0 # the length of the bar is 2*l c = 1.0 # body force P1 = 100.0 # The concentrated force at the right end of the bar P2 = 100.0 # The concentrated force at x0 = 15l/16 x0 = 15 * l / 16 L2Norm = 0 EnNorm = 0 L2NormEx = 0 EnNormEx = 0 P_element_index = int(x0 / (2 * l / model.nel)) for e in range(model.nel): if not flag: # The element which contains the concentrated force needs to be # handled individually when the force is not on a node if e == P_element_index: continue de = model.d[model.LM[:, e] - 1] # extract element nodal displacements IENe = model.IEN[:, e] - 1 # extract local connectivity information xe = model.x[IENe] # extract element x coordinates J = (xe[-1] - xe[0]) / 2 # compute Jacobian for i in range(ngp): xt = 0.5 * (xe[0] + xe[-1] ) + J * gp[i] # Gauss points in physical coordinates N = Nmatrix1D(xt, xe) # shape functions matrix B = Bmatrix1D(xt, xe) # derivative of shape functions matrix Ee = N @ model.E[IENe] # Young's modulus at element gauss points uh = N @ de # displacement at gauss point # Exact displacement if xt < x0: uex = c * (-xt**3 / 6 + 2 * l**2 * xt) / A / E + (P1 + P2) * xt / A / E else: uex = c * ( -xt**3 / 6 + 2 * l**2 * xt) / A / E + P1 * xt / A / E + 15 * P2 * l / 16 / A / E L2Norm += J * w[i] * (uex - uh)**2 L2NormEx += J * w[i] * (uex)**2 sh = B @ de # strain at Gauss points # Exact strain if xt < x0: sex = c * (-xt**2 / 2 + 2 * l**2) / A / E + (P1 + P2) / A / E else: sex = c * (-xt**2 / 2 + 2 * l**2) / A / E + P1 / A / E EnNorm += 0.5 * J * w[i] * Ee * (sex - sh)**2 EnNormEx += 0.5 * J * w[i] * Ee * (sex)**2 if not flag: # handle the element of P_element_index de = model.d[model.LM[:, P_element_index] - 1] # extract element nodal displacements IENe = model.IEN[:, P_element_index] - 1 # extract local connectivity information xe = model.x[IENe] # extract element x coordinates for i in range(ngp): J = (x0 - xe[0]) / 2 # compute Jacobian xt = 0.5 * (xe[0] + x0) + J * gp[i] # Gauss points in physical coordinates N = Nmatrix1D(xt, xe) # shape functions matrix B = Bmatrix1D(xt, xe) # derivative of shape functions matrix Ee = N @ model.E[IENe] # Young's modulus at element gauss points uh = N @ de # displacement at gauss point uex = c * (-xt**3 / 6 + 2 * l**2 * xt) / A / E + (P1 + P2) * xt / A / E L2Norm += J * w[i] * (uex - uh)**2 L2NormEx += J * w[i] * (uex)**2 sh = B @ de # strain at Gauss points sex = c * (-xt**2 / 2 + 2 * l**2) / A / E + (P1 + P2) / A / E EnNorm += 0.5 * J * w[i] * Ee * (sex - sh)**2 EnNormEx += 0.5 * J * w[i] * Ee * (sex)**2 for i in range(ngp): J = (xe[-1] - x0) / 2 # compute Jacobian xt = 0.5 * (x0 + xe[-1] ) + J * gp[i] # Gauss points in physical coordinates N = Nmatrix1D(xt, xe) # shape functions matrix B = Bmatrix1D(xt, xe) # derivative of shape functions matrix Ee = N @ model.E[IENe] # Young's modulus at element gauss points uh = N @ de # displacement at gauss point uex = c * (-xt**3 / 6 + 2 * l**2 * xt) / A / E + P1 * xt / A / E + 15 * P2 * l / 16 / A / E L2Norm += J * w[i] * (uex - uh)**2 L2NormEx += J * w[i] * (uex)**2 sh = B @ de # strain at Gauss points sex = c * (-xt**2 / 2 + 2 * l**2) / A / E + P1 / A / E EnNorm += 0.5 * J * w[i] * Ee * (sex - sh)**2 EnNormEx += 0.5 * J * w[i] * Ee * (sex)**2 L2Norm = sqrt(L2Norm) L2NormEx = sqrt(L2NormEx) EnNorm = sqrt(EnNorm) EnNormEx = sqrt(EnNormEx) # print stresses at element gauss points print('\nError norms') print('%13s %13s %13s %13s %13s' % ('h', 'L2Norm', 'L2NormRel', 'EnNorm', 'EnNormRel')) print( '%13.6E %13.6E %13.6E %13.6E %13.6E\n' % (2 / model.nel, L2Norm, L2Norm / L2NormEx, EnNorm, EnNorm / EnNormEx)) return 2 * l / model.nel, L2Norm, EnNorm