def basis_vectors(N, equation): xx = legslbndm(N) lepolys = gen_lepolys(N, xx) lepoly_x = dx(N, xx, lepolys) lepoly_xx = dxx(N, xx, lepolys) phi = basis(N, lepolys, equation) phi_x = basis_x(N, phi, lepoly_x, equation) phi_xx = basis_xx(N, phi_x, lepoly_xx, equation) return xx, lepolys, lepoly_x, lepoly_xx, phi, phi_x, phi_xx
def diff(N, T, D): x = legslbndm(N + 1) # D = torch.from_numpy(legslbdiff(N+1, x)).to(device).float() T_ = T.clone() for i in range(T.shape[0]): element = torch.mm(D, T[i, :].reshape(T.shape[1], 1)).reshape(T.shape[1], ) T_[i, :] = element T = T_.clone() del T_ return T
def weak_form(eps, N, f, u, alphas, lepolys, phi, phi_x, equation, nbfuncs, index=0): B, i, j = u.shape N -= 1 LHS = torch.zeros((B, 1, 1)).to(device).float() RHS = torch.zeros((B, 1, 1)).to(device).float() phi = torch.transpose(phi, 0, 1) denom = torch.square(torch.from_numpy(lepolys[N]).to(device).float()) denom = torch.transpose(denom, 0, 1) diffusion = 6 * eps * alphas[:, :, index] if equation == 'Standard': u_x = reconstruct(alphas, phi_x) ux_phi = u_x * phi[:, index] convection = torch.sum(ux_phi * 2 / (N * (N + 1)) / denom, axis=2) LHS[:, 0] = diffusion - convection RHS[:, 0] = torch.sum(2 * f * phi[:, index] / (N * (N + 1)) / denom, axis=2) elif equation == 'Burgers': phi_x = torch.transpose(phi_x, 0, 1) convection = torch.sum(u**2 * phi_x[:, index] / (N * (N + 1)) / denom, axis=2) LHS[:, 0] = diffusion - convection RHS[:, 0] = torch.sum(2 * f * phi[:, index] / (N * (N + 1)) / denom, axis=2) elif equation == 'Helmholtz': ku = 3.5 x = legslbndm(N + 1) D_ = torch.from_numpy(legslbdiff(N + 1, x)).to(device).float() D = torch.zeros((B, N + 1, N + 1)).to(device).float() D[:, :, :] = D_ phi_x = torch.transpose(phi_x, 0, 1) u_ = torch.transpose(u, 1, 2) temp = torch.bmm(D, u_) temp = torch.transpose(temp, 1, 2) diffusion = torch.sum(2 * temp * phi_x[:, index] / (N * (N + 1)) / denom, axis=2) reaction = ku * torch.sum( 2 * u * phi[:, index] / (N * (N + 1)) / denom, axis=2) LHS[:, 0] = -diffusion + reaction RHS[:, 0] = torch.sum(2 * f * phi[:, index] / (N * (N + 1)) / denom, axis=2) return LHS, RHS
LHS, RHS = 0, 0 for _ in range(10): phi_0 = lepolys[_] - lepolys[_+2] phi_x = D@phi_0 diffusion = -epsilon*(4*_+6)*(-1)*alphas[_] denom = lepolys[N]**2 convection = np.sum(u**2*phi_x/(N*(N+1))/denom) LHS += diffusion - convection RHS += np.sum(2*f*phi_0/(N*(N+1))/denom) else: u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing) data.append([u, f, alphas, params, epsilon]) return data x = sem.legslbndm(N+1) D = sem.legslbdiff(N+1, x) lepolys = gen_lepolys(N, x) # pprint(lepolys) if equation == 'Standard2D': lepolysx = gen_lepolysx(N, x, lepolys) # pprint(lepolysx) data = create_fast(N, epsilon, size, eps_flag, equation, sd, forcing) data = np.array(data, dtype=object) def save_obj(data, name, equation, kind): cwd = os.getcwd() path = os.path.join(cwd,'data', equation, kind)
def create_fast(N:int, epsilon:float, size:int, eps_flag=False): def func(t: float) -> float: # Random force m = 2*np.random.rand(4) - 1 f = m[0]*np.sin(m[1]*np.pi*t) + m[2]*np.cos(m[3]*np.pi*t) return f, m def gen_lepolys(N, x): lepolys = {} for i in range(N+3): lepolys[i] = sem.lepoly(i, x) return lepolys def generate(x, D, a, b, lepolys, epsilon): f, params = func(x) s_diag = np.zeros((N-1,1)) M = np.zeros((N-1,N-1)) for ii in range(1, N): k = ii - 1 s_diag[ii-1] = -(4*k+6)*b phi_k_M = D@(lepolys[k] + a*lepolys[k+1] + b*lepolys[k+2]) for jj in range(1,N): if abs(ii-jj) <=2: l = jj-1 psi_l_M = lepolys[l] + a*lepolys[l+1] + b*lepolys[l+2] M[jj-1,ii-1] = np.sum((psi_l_M*phi_k_M)*2/(N*(N+1))/(lepolys[N]**2)) S = s_diag*np.eye(N-1) g = np.zeros((N+1,)) for i in range(1,N+1): k = i-1 g[i-1] = (2*k+1)/(N*(N+1))*np.sum(f*(lepolys[k])/(lepolys[N]**2)) g[N-1] = 1/(N+1)*np.sum(f/lepolys[N]) bar_f = np.zeros((N-1,)) for i in range(1,N): k = i-1 bar_f[i-1] = g[i-1]/(k+1/2) + a*g[i]/(k+3/2) + b*g[i+1]/(k+5/2) Mass = epsilon*S-M u = np.linalg.solve(Mass, bar_f) alphas = np.copy(u) g[0], g[1] = u[0], u[1] + a*u[0] for i in range(3, N): k = i - 1 g[i-1] = u[i-1] + a*u[i-2] + b*u[i-3] g[N-1] = a*u[N-2] + b*u[N-3] g[N] = b*u[N-2] u = np.zeros((N+1,)) for i in range(1,N+2): _ = 0 for j in range(1, N+2): k = j-1 L = lepolys[k] _ += g[j-1]*L[i-1] _ = _[0] u[i-1] = _ return u, f, alphas, params def loop(N, epsilon, size, lepolys, eps_flag): if eps_flag == True: epsilons = np.random.uniform(1E0, 1E-6, SIZE) data = [] U, F, ALPHAS, PARAMS = [], [], [], [] for n in tqdm(range(size)): if eps_flag == True: epsilon = epsilons[n] u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon) data.append([u, f, alphas, params, epsilon]) return data x = sem.legslbndm(N+1) D = sem.legslbdiff(N+1, x) a, b = 0, -1 lepolys = gen_lepolys(N, x) return loop(N, epsilon, size, lepolys, eps_flag)
def create_fast(N: int, epsilon: float, size: int, eps_flag=False, equation='Standard', sd=1, forcing='uniform'): def func(x: np.ndarray, equation: str, sd: float, forcing: str) -> np.ndarray: if forcing == 'uniform': m = 3 + 2 * np.random.rand(2) n = np.pi * (1 + 2 * np.random.rand(2)) f = m[0] * np.sin(n[0] * x) + m[1] * np.cos(n[1] * x) m = np.array([m[0], m[1], n[0], n[1]]) elif forcing == 'normal': m = np.random.normal(0, sd, 4) f = m[0] * np.sin(m[1] * np.pi * x) + m[2] * np.cos( m[3] * np.pi * x) return f, m def gen_lepolys(N, x): lepolys = {} for i in range(N + 3): lepolys[i] = sem.lepoly(i, x) return lepolys def generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing): f, params = func(x, equation, sd, forcing) s_diag = np.zeros((N - 1, 1)) if equation == 'Standard': M = np.zeros((N - 1, N - 1)) for ii in range(1, N): k = ii - 1 s_diag[ii - 1] = -(4 * k + 6) * b phi_k_M = D @ (lepolys[k] + a * lepolys[k + 1] + b * lepolys[k + 2]) for jj in range(1, N): if np.abs(ii - jj) <= 2: l = jj - 1 psi_l_M = lepolys[l] + a * lepolys[ l + 1] + b * lepolys[l + 2] M[jj - 1, ii - 1] = np.sum((psi_l_M * phi_k_M) * 2 / (N * (N + 1)) / (lepolys[N]**2)) S = s_diag * np.eye(N - 1) g = np.zeros((N + 1, )) for i in range(1, N + 1): k = i - 1 g[i - 1] = (2 * k + 1) / (N * (N + 1)) * np.sum(f * (lepolys[k]) / (lepolys[N]**2)) g[N - 1] = 1 / (N + 1) * np.sum(f / lepolys[N]) bar_f = np.zeros((N - 1, )) for i in range(1, N): k = i - 1 bar_f[i - 1] = g[i - 1] / (k + 1 / 2) + a * g[i] / ( k + 3 / 2) + b * g[i + 1] / (k + 5 / 2) Mass = epsilon * S - M u = np.linalg.solve(Mass, bar_f) alphas = np.copy(u) g[0], g[1] = u[0], u[1] + a * u[0] for i in range(3, N): k = i - 1 g[i - 1] = u[i - 1] + a * u[i - 2] + b * u[i - 3] g[N - 1] = a * u[N - 2] + b * u[N - 3] g[N] = b * u[N - 2] u = np.zeros((N + 1, )) for i in range(1, N + 2): _ = 0 for j in range(1, N + 2): k = j - 1 L = lepolys[k] _ += g[j - 1] * L[i - 1] u[i - 1] = _[0] elif equation == 'Burgers': for ii in range(1, N): k = ii - 1 s_diag[k] = -(4 * k + 6) * b S = s_diag * np.eye(N - 1) Mass = epsilon * S error, tolerance, u_old, force = 1, 1E-9, 0 * f.copy(), f.copy() iterations = 0 while error > tolerance: f_ = force - u_old * (D @ u_old) g = np.zeros((N + 1, )) for i in range(1, N + 1): k = i - 1 g[k] = (2 * k + 1) / (N * (N + 1)) * np.sum(f_ * (lepolys[k]) / (lepolys[N]**2)) g[N - 1] = 1 / (N + 1) * np.sum(f_ / lepolys[N]) bar_f = np.zeros((N - 1, )) for i in range(1, N): k = i - 1 bar_f[k] = g[k] / (k + 1 / 2) + a * g[k + 1] / ( k + 3 / 2) + b * g[k + 2] / (k + 5 / 2) alphas = np.linalg.solve(Mass, bar_f) u_sol = np.zeros((N + 1, 1)) for ij in range(1, N): i_ind = ij - 1 u_sol += alphas[i_ind] * (lepolys[i_ind] + a * lepolys[i_ind + 1] + b * lepolys[i_ind + 2]) error = np.max(u_sol - u_old) u_old = u_sol iterations += 1 u = u_sol elif equation == 'BurgersT': M = np.zeros((N - 1, N - 1)) tol, T, dt = 1E-9, 5E-4, 1E-4 t_f = int(T / dt) u_pre, u_ans, f_ans, alphas_ans = np.sin(np.pi * x), [], [], [] for ii in range(1, N): k = ii - 1 s_diag[k] = -(4 * k + 6) * b phi_k_M = lepolys[k] + a * lepolys[k + 1] + b * lepolys[k + 2] for jj in range(1, N): if np.abs(ii - jj) <= 2: l = jj - 1 psi_l_M = lepolys[l] + a * lepolys[ l + 1] + b * lepolys[l + 2] entry = psi_l_M * phi_k_M * 2 / (N * (N + 1)) / (lepolys[N] **2) M[l, k] = np.sum(entry) S = s_diag * np.eye(N - 1) Mass = epsilon * S + (1 / dt) * M for t_idx in np.linspace(1, t_f, t_f, endpoint=True): error, tolerance, u_old, force = 1, tol, u_pre, np.cos( t_idx * dt) * f iterations = 0 while error > tolerance: f_ = force - u_old * (D @ u_old) + (1 / dt) * u_pre g = np.zeros((N + 1, )) for i in range(1, N + 1): k = i - 1 g[k] = (2 * k + 1) / (N * (N + 1)) * np.sum( f_ * (lepolys[k]) / (lepolys[N]**2)) g[N - 1] = 1 / (N + 1) * np.sum(f_ / lepolys[N]) bar_f = np.zeros((N - 1, )) for i in range(1, N): k = i - 1 bar_f[k] = g[k] / (k + 1 / 2) + a * g[k + 1] / ( k + 3 / 2) + b * g[k + 2] / (k + 5 / 2) alphas = np.linalg.solve(Mass, bar_f) u_sol = np.zeros((N + 1, 1)) for ij in range(1, N): i_ind = ij - 1 u_sol += alphas[i_ind] * (lepolys[i_ind] + a * lepolys[i_ind + 1] + b * lepolys[i_ind + 2]) error = np.max(u_sol - u_old) u_old = u_sol.copy() iterations += 1 u_ans.append(u_sol) f_ans.append(force) alphas_ans.append(alphas) u_pre = u_sol u, f, alphas = u_ans, f_ans, alphas_ans elif equation == 'Helmholtz': ku = 3.5 M = np.zeros((N - 1, N - 1)) for ii in range(1, N): k = ii - 1 s_diag[k] = -(4 * k + 6) * b[k] phi_k_M = lepolys[k] + a[k] * lepolys[k + 1] + b[k] * lepolys[ k + 2] for jj in range(1, N): if np.abs(ii - jj) <= 2: l = jj - 1 psi_l_M = lepolys[l] + a[l] * lepolys[ l + 1] + b[l] * lepolys[l + 2] entry = psi_l_M * phi_k_M * 2 / (N * (N + 1)) / (lepolys[N] **2) M[l, k] = np.sum(entry) S = s_diag * np.eye(N - 1) g = np.zeros((N + 1, )) for i in range(1, N + 1): k = i - 1 g[k] = (2 * k + 1) / (N * (N + 1)) * np.sum(f * (lepolys[k]) / (lepolys[N]**2)) g[N] = 1 / (N + 1) * np.sum(f / lepolys[N]) bar_f = np.zeros((N - 1, )) for i in range(1, N): k = i - 1 bar_f[k] = g[k] / (k + 1 / 2) + a[k] * g[k + 1] / ( k + 3 / 2) + b[k] * g[k + 2] / (k + 5 / 2) Mass = -S + ku * M alphas = np.linalg.solve(Mass, bar_f) u = np.zeros((N + 1, 1)) for ij in range(1, N): i_ind = ij - 1 u += alphas[i_ind] * (lepolys[i_ind] + a[i_ind] * lepolys[i_ind + 1] + b[i_ind] * lepolys[i_ind + 2]) return u, f, alphas, params def loop(N, epsilon, size, lepolys, eps_flag, equation, a, b, forcing): if eps_flag == True: epsilons = np.random.uniform(1E0, 1E-6, SIZE) data = [] U, F, ALPHAS, PARAMS = [], [], [], [] for n in tqdm(range(size)): if eps_flag == True: epsilon = epsilons[n] if equation == 'BurgersT': u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing) for i, u_ in enumerate(u): if i < len(u): data.append([u[i], f[i], alphas[i], params, epsilon]) elif equation == 'Burgers': u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing) LHS, RHS = 0, 0 for _ in range(10): phi_0 = lepolys[_] - lepolys[_ + 2] phi_x = D @ phi_0 diffusion = -epsilon * (4 * _ + 6) * (-1) * alphas[_] denom = lepolys[N]**2 convection = np.sum(u**2 * phi_x / (N * (N + 1)) / denom) LHS += diffusion - convection RHS += np.sum(2 * f * phi_0 / (N * (N + 1)) / denom) while np.abs(LHS - RHS) > 1E-5 and np.linalg.norm( u, ord=2) < 1E-2: u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing) LHS, RHS = 0, 0 for _ in range(10): phi_0 = lepolys[_] - lepolys[_ + 2] phi_x = D @ phi_0 diffusion = -epsilon * (4 * _ + 6) * (-1) * alphas[_] denom = lepolys[N]**2 convection = np.sum(u**2 * phi_x / (N * (N + 1)) / denom) LHS += diffusion - convection RHS += np.sum(2 * f * phi_0 / (N * (N + 1)) / denom) else: u, f, alphas, params = generate(x, D, a, b, lepolys, epsilon, equation, sd, forcing) data.append([u, f, alphas, params, epsilon]) return data x = sem.legslbndm(N + 1) D = sem.legslbdiff(N + 1, x) lepolys = gen_lepolys(N, x) if equation == 'Helmholtz': a, b = np.zeros((N + 1, )), np.zeros((N + 1, )) for i in range(1, N + 2): k = i - 1 b[k] = -k * (k + 1) / ((k + 2) * (k + 3)) else: a, b = 0, -1 return loop(N, epsilon, size, lepolys, eps_flag, equation, a, b, forcing)
z, cmap=cm.coolwarm, linewidth=0, antialiased=False) plt.xlim(-1, 1) plt.ylim(-1, 1) plt.grid(alpha=0.618) plt.xlabel('$x$') plt.ylabel('$y$') plt.show() # exit() if __name__ == '__main__': start = time() x = legslbndm(N + 1) y = x.copy() D = legslbdiff(N + 1, x) D2 = D @ D D2 = D2[1:-1, 1:-1] lepolys = gen_lepolys(N, x) lepolysx = gen_lepolysx(N, x, lepolys) I = np.eye(N - 1) L = np.kron(I, D2) + np.kron(D2, I) x1, y1 = np.meshgrid(x, x) f = f2D(x1, y1) f_ = f[1:-1, 1:-1] f_ = f_.ravel() u = np.linalg.solve(-L, f_) xx, yy = np.meshgrid(x[1:-1], x[1:-1]) uu = np.zeros_like(x1)
def plotter(xx, sample, epoch, a=None, u=None, DE=None, title='alpha', ks=7): def relative_l2(measured, theoretical): return np.linalg.norm(measured - theoretical, ord=2) / np.linalg.norm( theoretical, ord=2) def relative_linf(measured, theoretical): return np.linalg.norm(measured - theoretical, ord=np.inf) / np.linalg.norm(theoretical, ord=np.inf) def mae(measured, theoretical): return np.linalg.norm(measured - theoretical, ord=1) / len(theoretical) aa = sample['a'][0, 0, :].to('cpu').detach().numpy() uu = sample['u'][0, 0, :].to('cpu').detach().numpy() ff = sample['f'][0, 0, :].to('cpu').detach().numpy() x_ = legslbndm(len(xx) - 2) xxx = np.linspace(-1, 1, len(ff), endpoint=True) if a is not None: ahat = a[0, :].to('cpu').detach().numpy() mae_error_a = mae(ahat, aa) l2_error_a = relative_l2(ahat, aa) linf_error_a = relative_linf(ahat, aa) plt.figure(1, figsize=(10, 6)) plt.title(f'Alphas Example Epoch {epoch}\n'\ f'Alphas MAE Error: {np.round(mae_error_a, 6)}\n'\ f'Alphas Rel. $L_2$ Error: {np.round(float(l2_error_a), 6)}\n'\ f'Alphas Rel. $L_\\infty$ Error: {np.round(float(linf_error_a), 6)}') plt.plot(x_, aa, 'r-', mfc='none', label='$\\alpha$') plt.plot(x_, ahat, 'bo', mfc='none', label='$\\hat{\\alpha}$') # plt.plot(xxx, ff, 'g-', label='$f$') plt.xlim(-1, 1) plt.grid(alpha=0.618) plt.xlabel('$x$') plt.ylabel('$y$') plt.legend(shadow=True) plt.savefig( f'./pics/{title}_ks{ks}_epoch{str(epoch).zfill(5)}_alphas.png', bbox_inches='tight') plt.close(1) if u is not None: uhat = u[0, :].to('cpu').detach().numpy() mae_error_u = mae(uhat, uu) l2_error_u = relative_l2(uhat, uu) linf_error_u = relative_linf(uhat, uu) plt.figure(2, figsize=(10, 6)) plt.title(f'Reconstruction Example Epoch {epoch}\n'\ f'Reconstruction MAE Error: {np.round(mae_error_u, 6)}\n'\ f'Reconstruction Rel. $L_2$ Error: {np.round(float(l2_error_u), 6)}\n'\ f'Reconstruction Rel. $L_\\infty$ Error: {np.round(float(linf_error_u), 6)}') plt.plot(xx, uu, 'r-', mfc='none', label='$u$') plt.plot(xx, uhat.T, 'bo', mfc='none', label='$\\hat{u}$') plt.xlim(-1, 1) plt.grid(alpha=0.618) plt.xlabel('$x$') plt.ylabel('$y$') plt.legend(shadow=True) plt.savefig( f'./pics/{title}_ks{ks}_epoch{str(epoch).zfill(5)}_reconstruction.png', bbox_inches='tight') # plt.show() plt.close(2) if DE is not None: de = DE[0, :].to('cpu').detach().numpy() plt.figure(3, figsize=(10, 6)) mae_error_de = mae(de, ff) l2_error_de = relative_l2(de, ff) linf_error_de = relative_linf(de, ff) plt.title(f'DE Example Epoch {epoch}\n'\ f'DE MAE Error: {np.round(mae_error_de, 6)}\n'\ f'DE Rel. $L_2$ Error: {np.round(float(l2_error_de), 6)}\n'\ f'DE Rel. $L_\\infty$ Error: {np.round(float(linf_error_de), 6)}') plt.plot(xxx, ff, 'g-', label='$f$') plt.plot(xxx, de, 'co', mfc='none', label='ODE') plt.xlim(-1, 1) plt.grid(alpha=0.618) plt.xlabel('$x$') plt.ylabel('$y$') plt.legend(shadow=True) plt.savefig(f'./pics/{title}_ks{ks}_epoch{str(epoch).zfill(5)}_DE.png', bbox_inches='tight') # plt.show() plt.close(3)