| import numpy as np |
| from scipy.sparse import csr_matrix |
| from scipy.sparse.linalg import spsolve |
|
|
| def neb_beam_matrices(nx, dx, E, Ix, rho, S, cy): |
| """ |
| Compute the FE matrices for Navier-Euler-Bernoulli beams |
| """ |
| npt = nx + 1 |
| ndof = 2 * npt |
| doflist = np.arange(0, 2*nx, 2) |
| on1 = np.ones(nx) |
|
|
| Ki = np.concatenate([ |
| doflist, doflist, doflist, doflist, |
| doflist+1, doflist+1, doflist+1, doflist+1, |
| doflist+2, doflist+2, doflist+2, doflist+2, |
| doflist+3, doflist+3, doflist+3, doflist+3 |
| ]) |
| Kj = np.concatenate([ |
| doflist, doflist+1, doflist+2, doflist+3, |
| doflist, doflist+1, doflist+2, doflist+3, |
| doflist, doflist+1, doflist+2, doflist+3, |
| doflist, doflist+1, doflist+2, doflist+3 |
| ]) |
| Kv = E*Ix/(dx**3) * np.concatenate([ |
| 12*on1, 6*dx*on1, -12*on1, 6*dx*on1, |
| 6*dx*on1, 4*dx**2*on1, -6*dx*on1, 2*dx**2*on1, |
| -12*on1, -6*dx*on1, 12*on1, -6*dx*on1, |
| 6*dx*on1, 2*dx**2*on1, -6*dx*on1, 4*dx**2*on1 |
| ]) |
| Kfull = csr_matrix((Kv, (Ki, Kj)), shape=(ndof, ndof)) |
|
|
| Mv1 = rho*S*dx/420 * np.concatenate([ |
| 156*on1, 22*dx*on1, 54*on1, -13*dx*on1, |
| 22*dx*on1, 4*dx**2*on1, 13*dx*on1, -3*dx**2*on1, |
| 54*on1, 13*dx*on1, 156*on1, -22*dx*on1, |
| -13*dx*on1, -3*dx**2*on1, -22*dx*on1, 4*dx**2*on1 |
| ]) |
| Mfull = csr_matrix((Mv1, (Ki, Kj)), shape=(ndof, ndof)) |
|
|
| Cv = cy*dx/420 * np.concatenate([ |
| 156*on1, 22*dx*on1, 54*on1, -13*dx*on1, |
| 22*dx*on1, 4*dx**2*on1, 13*dx*on1, -3*dx**2*on1, |
| 54*on1, 13*dx*on1, 156*on1, -22*dx*on1, |
| -13*dx*on1, -3*dx**2*on1, -22*dx*on1, 4*dx**2*on1 |
| ]) |
| Cfull = csr_matrix((Cv, (Ki, Kj)), shape=(ndof, ndof)) |
|
|
| return Kfull, Cfull, Mfull |
|
|
| def newmark1step_mrhs(M, C, K, f, u0, v0, a0, dt, beta, gamma): |
| """ |
| Computes one step of the Newmark algorithm |
| """ |
| fatK = K + 1/(beta*dt**2)*M + gamma/(beta*dt)*C |
| b = f + C * (gamma/(beta*dt)*u0 + (gamma/beta - 1)*v0 + dt/2*(gamma/beta - 1)*a0) + M * (1/(beta*dt**2)*u0 + 1/(beta*dt)*v0 + (1/(2*beta) - 1)*a0) |
| u = spsolve(fatK, b) |
| a = 1/(beta*dt**2) * (u - u0 - dt*v0 - (dt**2/2)*(1-2*beta)*a0) |
| v = v0 + dt * ((1 - gamma)*a0 + gamma*a) |
| return u, v, a |
|
|
| def Newmark2N(M, C, K, f, u0, v0, dt, beta, gamma): |
| """ |
| Solves the dynamic system with Newmark approach |
| """ |
| ndof, ntime = f.shape |
| u = np.zeros((ndof, ntime)) |
| v = np.zeros((ndof, ntime)) |
| a = np.zeros((ndof, ntime)) |
| |
| up = u0 |
| vp = v0 |
| ap = spsolve(M, f[:, 0] - C @ vp - K @ up) |
| |
| fatK = K + 1/(beta*dt**2)*M + gamma/(beta*dt)*C |
| fatK_inv = np.linalg.inv(fatK.toarray()) |
| |
| u[:, 0] = u0 |
| v[:, 0] = v0 |
| a[:, 0] = ap |
| |
| for i in range(1, ntime): |
| b = f[:, i] + C @ (gamma/(beta*dt)*up + (gamma/beta - 1)*vp + dt/2*(gamma/beta - 2)*ap) + M @ (1/(beta*dt**2)*up + 1/(beta*dt)*vp + (1/(2*beta) - 1)*ap) |
| u[:, i] = fatK_inv @ b |
| a[:, i] = 1/(beta*dt**2) * (u[:, i] - up - dt*vp - (dt**2/2)*(1-2*beta)*ap) |
| v[:, i] = vp + dt * ((1 - gamma)*ap + gamma*a[:, i]) |
| up, vp, ap = u[:, i], v[:, i], a[:, i] |
| |
| return u, v, a |
|
|
| def Bconstruct(M, C, K, nA, dt, beta, gamma): |
| nx = M.shape[0] |
| B = np.zeros((3*nx, nx)) |
| for j in range(nx): |
| u0 = np.zeros(nx) |
| v0 = np.zeros(nx) |
| a0 = np.zeros(nx) |
| eta = np.zeros(nx) |
| eta[j] = 1 |
| u, v, a = newmark1step_mrhs(M, C, K, eta, u0, v0, a0, dt, beta, gamma) |
| B[:, j] = np.concatenate([u, v, a]) |
| return B |
|
|
| def Fconstruct(M, C, K, dt, beta, gamma): |
| nx = M.shape[0] |
| M1 = np.eye(nx) |
| M2 = np.zeros((nx, nx)) |
| u0 = np.block([M1, M2, M2]) |
| v0 = np.block([M2, M1, M2]) |
| a0 = np.block([M2, M2, M1]) |
| f = np.zeros(nx) |
| u, v, a = newmark1step_mrhs(M, C, K, f, u0, v0, a0, dt, beta, gamma) |
| F = np.concatenate([u, v, a]) |
| return F |