def solver3D(degree, dim, my_f): cheb = lf.chebyshev_nodes(degree + 1) #Lista nodi chebichev n = degree + 1 # Dim poly space q, w = leggauss(n) # Gauss between -1 and 1 q = (q + 1) / 2 # to go back to 0,1 w = w / 2 lag_bas = [] lag_bas_deriv = [] V = [] V_prime = [] #lagrangian base per i punti chebichev for i in range(len(cheb)): lag_bas.append(lf.lagrange_basis(cheb, i)) lag_bas_deriv.append(lf.lagrange_basis_derivatives(cheb, i)) Vq = zeros((n, len(q))) Vpq = zeros((n, len(q))) #Le righe di Vq sono le funzioni di base calcolate sui punti di quadratura for i in range(n): Vq[i] = lag_bas[i](q) Vpq[i] = lag_bas_deriv[i](q) #VVV = einsum('ij,kl,nm -> inkljm', Vq, Vq, Vq, optimize=True) #VVVp = einsum('ij,kl,nm -> inkljm', Vq, Vq, Vpq, optimize=True) #VVpV = einsum('ij,kl,nm -> inkljm', Vq, Vpq, Vq, optimize=True) #VpVV = einsum('ij,kl,nm -> inkljm', Vpq, Vq, Vq, optimize=True) #VVV = reshape(VVV, (prod(VVV.shape[:dim]), prod(VVV.shape[dim:]))) #VVVp = reshape(VVVp, (prod(VVVp.shape[:dim]), prod(VVVp.shape[dim:]))) #VVpV = reshape(VVpV, (prod(VVpV.shape[:dim]), prod(VVpV.shape[dim:]))) #VpVV = reshape(VpVV, (prod(VpVV.shape[:dim]), prod(VpVV.shape[dim:]))) #W = einsum('i,j,k -> ijk', w, w, w, optimize=True) #W = reshape(W, (prod(W.shape[:dim]))) latticeq_points = array([[[[qx, qy, qz] for qz in q] for qy in q] for qx in q]) latticeq_points = latticeq_points.reshape(len(q) * len(q) * len(q), dim) lpoint_x = array( [latticeq_points[i, 0] for i in range(len(latticeq_points))]) lpoint_y = array( [latticeq_points[i, 1] for i in range(len(latticeq_points))]) lpoint_z = array( [latticeq_points[i, 2] for i in range(len(latticeq_points))]) # ------------------------------------------------- print "Starting einsum A and M..." Atmp = einsum('jq, iq, q -> ji', Vpq, Vpq, w, optimize=True) Mtmp = einsum('jq, iq, q -> ji', Vq, Vq, w, optimize=True) A = einsum('il, jm, kn -> ijklmn', Atmp, Mtmp, Mtmp, optimize=True) A += einsum('il, jm, kn -> ijklmn', Mtmp, Atmp, Mtmp, optimize=True) A += einsum('il, jm, kn -> ijklmn', Mtmp, Mtmp, Atmp, optimize=True) M = einsum('il, jm, kn -> ijklmn', Mtmp, Mtmp, Mtmp, optimize=True) # ------------------------------------------------- print "Starting einsum rhs..." my_f = array(my_f(lpoint_x, lpoint_y, lpoint_z)).reshape(n, n, n) rhs = einsum('ijk, li, i -> jkl', my_f, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) # ------------------------------------------------- A = A.reshape(n**3, n**3) M = M.reshape(n**3, n**3) rhs = rhs.reshape(n**3) # ------------------------------------------------- print "Solving linear system..." u_fe = linalg.solve(A + M, rhs) Vcheb = zeros((n, len(cheb))) for j in range(degree + 1): Vcheb[j] = lag_bas[j](cheb) C = einsum('is, jk, nm -> skmijn', Vcheb, Vcheb, Vcheb, optimize=True) sol = einsum('skmijn, ijn', C, u_fe.reshape((n, n, n)), optimize=True) return sol.reshape(n, n, n)
if __name__ == "__main__": # Let us pick up this test function to test our solver u_exact = lambda x, y, z: cos(pi * x) * cos(pi * y) * cos(pi * z) my_f = lambda x, y, z: (3 * (pi**2) + 1) * cos(pi * y) * cos(pi * x) * cos( pi * z) #--------- Plotting a section of our FE solution -------- dim = 3 # space dim of the problem degree = 8 # degree of polynomial bases u_fem = solver3D(degree, dim, my_f) cheby = lf.chebyshev_nodes(degree + 1) X, Y = meshgrid(cheby, cheby) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot_surface(X, Y, u_fem[:, :, 0], cmap=cm.jet) plt.show() # --------------- Error Computation --------------------- L2_err = [] deg_start = 2 deg_end = 12 deg_step = 1
L2_err_iter_prec = [] L2_err_iter_noprec = [] #t_dir = [] # time direct method t_iter_prec = [] # time iteractive method with preconditioner t_iter_noprec = [] # time iteractive method without preconditioner deg_start = 2 deg_end = 35 deg_step = 1 for deg in range(deg_start, deg_end, deg_step): print "---------------------------------", deg u_ext_chebp = [] cheb = lf.chebyshev_nodes(deg + 1) start = time.time() FE3D = FiniteElem3D(deg, dim, my_f) end = time.time() tot = end - start u_fem_iter_prec = FE3D[0] u_fem_iter_prec = u_fem_iter_prec.reshape(len(cheb)**3, ) u_fem_iter_noprec = FE3D[1] u_fem_iter_noprec = u_fem_iter_noprec.reshape(len(cheb)**3, )
def FiniteElem3D(degree, dim, my_f): cheb = lf.chebyshev_nodes(degree + 1) #Lista nodi chebichev n = degree + 1 # Dim poly space q, w = leggauss(n) # Gauss between -1 and 1 q = (q + 1) / 2 # to go back to 0,1 w = w / 2 lag_bas = [] lag_bas_deriv = [] #lagrangian base per i punti chebichev for i in range(len(cheb)): lag_bas.append(lf.lagrange_basis(cheb, i)) lag_bas_deriv.append(lf.lagrange_basis_derivatives(cheb, i)) Vq = zeros((n, len(q))) Vpq = zeros((n, len(q))) #Le righe di Vq sono le funzioni di base calcolate sui punti di quadratura for i in range(n): Vq[i] = lag_bas[i](q) Vpq[i] = lag_bas_deriv[i](q) # ------------------------------------------------- latticeq_points = array([[[[qx, qy, qz] for qz in q] for qy in q] for qx in q]) latticeq_points = latticeq_points.reshape(len(q) * len(q) * len(q), dim) lpoint_x = array( [latticeq_points[i, 0] for i in range(len(latticeq_points))]) lpoint_y = array( [latticeq_points[i, 1] for i in range(len(latticeq_points))]) lpoint_z = array( [latticeq_points[i, 2] for i in range(len(latticeq_points))]) # ------------------------------------------------- print "Starting Matrix Free..." A1mf = einsum('jq, iq, q -> ji', Vpq, Vpq, w, optimize=True) M1mf = einsum('jq, iq, q -> ji', Vq, Vq, w, optimize=True) A = einsum('ii, jj, kk -> ijk', A1mf, M1mf, M1mf, optimize=True) A += einsum('ii, jj, kk -> ijk', M1mf, A1mf, M1mf, optimize=True) A += einsum('ii, jj, kk -> ijk', M1mf, M1mf, A1mf, optimize=True) M = einsum('ii, jj, kk -> ijk', M1mf, M1mf, M1mf, optimize=True) def matrix_free_lhs(u_fe): u_fe = u_fe.reshape((n, n, n)) u_tmp = einsum('iq, qjl -> ijl', M1mf, u_fe, optimize=True) u_tmp = einsum('jq, iql -> ijl', M1mf, u_tmp, optimize=True) u = einsum('kq, ijq -> ijk', M1mf, u_tmp, optimize=True) u_tmp = einsum('iq, qjl -> ijl', A1mf, u_fe, optimize=True) u_tmp = einsum('jq, iql -> ijl', M1mf, u_tmp, optimize=True) u += einsum('kq, ijq -> ijk', M1mf, u_tmp, optimize=True) u_tmp = einsum('iq, qjl -> ijl', M1mf, u_fe, optimize=True) u_tmp = einsum('jq, iql -> ijl', A1mf, u_tmp, optimize=True) u += einsum('kq, ijq -> ijk', M1mf, u_tmp, optimize=True) u_tmp = einsum('iq, qjl -> ijl', M1mf, u_fe, optimize=True) u_tmp = einsum('jq, iql -> ijl', M1mf, u_tmp, optimize=True) u += einsum('kq, ijq -> ijk', A1mf, u_tmp, optimize=True) return u.reshape((n**3, )) MF = scipy.sparse.linalg.LinearOperator((n**3, n**3), matvec=matrix_free_lhs) my_f = array(my_f(lpoint_x, lpoint_y, lpoint_z)).reshape(n, n, n) rhs = einsum('ijk, li, i -> jkl', my_f, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) # ------------------------------------------------- A = A.reshape(n**3, ) M = M.reshape(n**3, ) rhs = rhs.reshape(n**3) print "Iteractive Method without Preconditioner..." start = time.time() u_fe_iter_noprec = scipy.sparse.linalg.cg(MF, rhs, x0=None, M=identity(n**3), tol=1e-10) end = time.time() time_iter_noprec = end - start t_iter_noprec.append(time_iter_noprec) u_fe_iter_noprec = array(u_fe_iter_noprec[0]) # ---------- Iterative Conjugate Gradient with Prec ---------- print "Iteractive Method with Preconditioner..." start = time.time() #invP = diag(1./diag(M)) invP = diag(1. / (A + M)) u_fe_iter_prec = scipy.sparse.linalg.cg(MF, rhs, x0=None, M=invP, tol=1e-10) end = time.time() time_iter_prec = end - start t_iter_prec.append(time_iter_prec) u_fe_iter_prec = array(u_fe_iter_prec[0]) # ------------------------------------------------- Vcheb = zeros((n, len(cheb))) for j in range(degree + 1): Vcheb[j] = lag_bas[j](cheb) C = einsum('is, jk, nm -> skmijn', Vcheb, Vcheb, Vcheb, optimize=True) #sol_dir = einsum('skmijn, ijn', C, u_fe_dir.reshape((n, n, n)), optimize=True) sol_iter_prec = einsum('skmijn, ijn', C, u_fe_iter_prec.reshape((n, n, n)), optimize=True) sol_iter_noprec = einsum('skmijn, ijn', C, u_fe_iter_noprec.reshape((n, n, n)), optimize=True) return sol_iter_prec.reshape(n, n, n), sol_iter_noprec.reshape(n, n, n)
def FiniteElem3D(degree, dim, my_f): cheb = lf.chebyshev_nodes(degree+1) #Lista nodi chebichev n = degree + 1 # Dim poly space q,w = leggauss(n) # Gauss between -1 and 1 q = (q+1)/2 # to go back to 0,1 w = w/2 lag_bas=[] lag_bas_deriv=[] #lagrangian base per i punti chebichev for i in range(len(cheb)): lag_bas.append(lf.lagrange_basis(cheb,i)) lag_bas_deriv.append(lf.lagrange_basis_derivatives(cheb,i)) Vq = zeros((n, len(q))) Vpq = zeros((n, len(q))) #Le righe di Vq sono le funzioni di base calcolate sui punti di quadratura for i in range(n): Vq[i] = lag_bas[i](q) Vpq[i] = lag_bas_deriv[i](q) # ------------------------------------------------- latticeq_points = array([[[[qx,qy,qz] for qz in q] for qy in q ] for qx in q]) latticeq_points = latticeq_points.reshape(len(q)*len(q)*len(q),dim) lpoint_x = array([latticeq_points[i,0] for i in range(len(latticeq_points))]) lpoint_y = array([latticeq_points[i,1] for i in range(len(latticeq_points))]) lpoint_z = array([latticeq_points[i,2] for i in range(len(latticeq_points))]) # ------------------------------------------------- print "Starting einsum A and M..." Atmp = einsum('jq, iq, q -> ji', Vpq, Vpq, w, optimize=True) Mtmp = einsum('jq, iq, q -> ji', Vq, Vq, w, optimize=True) A = einsum('il, jm, kn -> ijklmn', Atmp, Mtmp, Mtmp, optimize=True) A += einsum('il, jm, kn -> ijklmn', Mtmp, Atmp, Mtmp, optimize=True) A += einsum('il, jm, kn -> ijklmn', Mtmp, Mtmp, Atmp, optimize=True) M = einsum('il, jm, kn -> ijklmn', Mtmp, Mtmp, Mtmp, optimize=True) # ------------------------------------------------- print "Starting einsum rhs..." my_f = array(my_f(lpoint_x,lpoint_y,lpoint_z)).reshape(n,n,n) rhs = einsum('ijk, li, i -> jkl', my_f, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) rhs = einsum('ijk, li, i -> jkl', rhs, Vq, w, optimize=True) # ------------------------------------------------- A = A.reshape(n**3,n**3) M = M.reshape(n**3,n**3) rhs = rhs.reshape(n**3) #---------- Direct Method ------------------------- print "Direct Method ..." start = time.time() u_fe_dir = linalg.solve( A + M, rhs) end = time.time() time_dir = end - start t_dir.append(time_dir) # ---------- Iterative Conjugate Gradient without Prec---------- print "Iteractive Method without Preconditioner..." start = time.time() u_fe_iter_noprec = scipy.sparse.linalg.cg( A + M, rhs, M = identity(len(A)), tol = 1e-10) end = time.time() time_iter_noprec = end - start t_iter_noprec.append(time_iter_noprec) u_fe_iter_noprec = array(u_fe_iter_noprec[0]) # ---------- Iterative Conjugate Gradient with Prec ---------- print "Iteractive Method with Preconditioner..." start = time.time() invP = diag(1./diag(A + M)) u_fe_iter_prec = scipy.sparse.linalg.cg( A + M, rhs, M = invP, tol = 1e-10) end = time.time() time_iter_prec = end - start t_iter_prec.append(time_iter_prec) u_fe_iter_prec = array(u_fe_iter_prec[0]) # ------------------------------------------------- Vcheb = zeros((n, len(cheb))) for j in range(degree + 1): Vcheb[j] = lag_bas[j](cheb) C = einsum('is, jk, nm -> skmijn', Vcheb, Vcheb, Vcheb, optimize=True) sol_dir = einsum('skmijn, ijn', C, u_fe_dir.reshape((n, n, n)), optimize=True) sol_iter_prec = einsum('skmijn, ijn', C, u_fe_iter_prec.reshape((n, n, n)), optimize=True) sol_iter_noprec = einsum('skmijn, ijn', C, u_fe_iter_noprec.reshape((n, n, n)), optimize=True) return sol_dir.reshape(n,n,n), sol_iter_prec.reshape(n,n,n), sol_iter_noprec.reshape(n,n,n)