def elliptic_heterogenous(n): K = np.array([[1, 0], [0, 1]]) x = sym.Symbol('x') y = sym.Symbol('y') k = np.eye(2) u_exact = x * y * (1 - x) * (1 - y) - 1 # u_exact = sym.cos(y*math.pi)*sym.cosh(x*math.pi) f = -divergence(gradient(u_exact, [x, y]), [x, y]) print(f) f = sym.lambdify([x, y], f) u_exact = sym.lambdify([x, y], u_exact) T = lambda p: np.array([p[0], p[1]]) mesh = Mesh(n, n, T, centers_at_bc=True) mesh.plot_funtion(f, 'source') # k = sym.lambdify([x,y],k) # k = mesh.interpolate(k) # permability = np.reshape(k,(mesh.midpoints.shape[0],mesh.midpoints.shape[1]),order='F') #permability[2:6,14:19] = 0.1 A = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) A = compute_matrix(mesh, K, A) F = compute_vector(mesh, f, u_exact) u = np.linalg.solve(A, F) Af = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) Af = compute_matrix_FEM(mesh, K, Af) Ff = compute_vector_FEM(mesh, f, u_exact) uf = np.linalg.solve(Af, Ff) uf = np.reshape(uf, (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1])) uf = np.ravel(uf, order='F') mesh.plot_vector(u, 'FVML') mesh.plot_vector(uf, 'FEM') mesh.plot_funtion(u_exact, 'excact') e = u - mesh.interpolate(u_exact) mesh.plot_vector(e, 'error') # mesh.plot_vector(uf,'FEM') mesh.plot_vector(uf - u, 'difference') (l2, m) = compute_error(mesh, uf, u_exact) print('l2 fem', l2) print('max fem', m) return compute_error(mesh, u, u_exact) # (l2,m) = elliptic_heterogenous(10) # print(l2) # print(m)
def richards_equation(): K = p**2 theta = 1/(1-p) f = sym.diff(theta.subs(p,u_exact),t)-divergence(gradient(u_exact + y ,[x,y]),[x,y],K.subs(p,u_exact)) print(sym.simplify(f)) f = sym.lambdify([x,y,t],f) equation = Richards(max_edge = 0.125) physics = equation.getPhysics() physics['source'] = f physics['neumann'] = sym.lambdify([x,y,t],K.subs(p,u_exact)*sym.diff(u_exact,y)) mass,stiffness,source,error = FEM_solver(equation.geometry, equation.physics) B = mass() th = np.linspace(0,1,64) tau = th[1]-th[0] TOL = 0.000005 L = 3 u = vectorize(u_exact.subs(t,0),equation.geometry) A = stiffness(lambda x:1,u) theta = lambda x: 1/(1-x) K = lambda x: x**2 def L_scheme(u_j,u_n,TOL,L,K,tau,f): rhs = L*B@u_j+mass(theta,u_n)-mass(theta,u_j)+tau*f A = stiffness(K,u_j) lhs = L*B+tau*A u_j_n = np.linalg.solve(lhs,rhs) print(np.linalg.norm(u_j_n-u_j)) if np.linalg.norm(u_j_n-u_j)>TOL + TOL*np.linalg.norm(u_j_n): return L_scheme(u_j_n,u_n,TOL,L,K,tau,source(i,u_j_n,K)) else: return u_j_n for i in th[1:]: u = L_scheme(u,u,TOL,L,K,tau,source(i,u,K)) u_e = vectorize(u_exact.subs(t,i),equation.geometry) error.l2_error(u,u_exact.subs(t,i)) plot(u,equation.geometry) plot(u_e,equation.geometry) plot(u-u_e,equation.geometry) error.max_error(u,u_exact.subs(t,i))
def run_heat(timestep, num_nodes): #Construct the data given a solution K = np.array([[1, 0], [0, 1]]) x = sym.Symbol('x') y = sym.Symbol('y') t = sym.Symbol('t') u_exact = -0.1 * sym.sin(math.pi * x) * sym.sin(math.pi * y) * t - 1 # u_exact = -t*x*y*(1-x)*(1-y) f = sym.diff(u_exact, t) - divergence(gradient(u_exact, [x, y]), [x, y]) f = sym.lambdify([x, y, t], f) u_exact = sym.lambdify([x, y, t], u_exact) #Define the mesh def random_perturbation(h, aspect): return lambda p: np.array([ random.uniform(0, h) * random.choice([-1, 1]) + p[0] - 0.5 * p[1], (1 / aspect) * random.uniform(0, h) * random.choice([-1, 1]) + p[1] ]) T = lambda p: np.array([p[0], p[1]]) nx = num_nodes ny = num_nodes mesh = Mesh(nx, ny, T, ghostboundary=True) h = np.linalg.norm(mesh.nodes[1, 1, :] - mesh.nodes[0, 0, :]) print('h ', h) #make mass and gravitation matrices mass = mass_matrix(mesh) def compute_error(mesh, u, u_fabric): cx = mesh.cell_centers.shape[1] cy = mesh.cell_centers.shape[0] u_fabric_vec = u.copy() volumes = u.copy() for i in range(cy): for j in range(cx): u_fabric_vec[mesh.meshToVec(i, j)] = u_fabric( mesh.cell_centers[i, j, 0], mesh.cell_centers[i, j, 1]) volumes[mesh.meshToVec(i, j)] = mesh.volumes[i, j] L2err = math.sqrt( np.square(u - u_fabric_vec).T @ volumes / (np.ones(volumes.shape).T @ volumes)) maxerr = np.max(np.abs(u - u_fabric_vec)) return (L2err, maxerr) #Time discretization time_partition = np.linspace(0, 1, math.ceil(1 / timestep)) tau = time_partition[1] - time_partition[0] u = mesh.interpolate(lambda x, y: u_exact(x, y, 0)) for t in time_partition[1:]: A = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) lhs = tau * stiffness(mesh, K, A) + mass rhs = tau * compute_vector(mesh, lambda x, y: f(x, y, t), lambda x, y: u_exact(x, y, t)) + mass @ u u = np.linalg.solve(lhs, rhs) # mesh.plot_vector(u,'numerical solution') # mesh.plot_funtion(lambda x,y:u_exact(x,y,t),'exact solution') # e = u - mesh.interpolate(lambda x,y: u_exact(x,y,t)) # mesh.plot_vector(e,'error') return compute_error(mesh, u, lambda x, y: u_exact(x, y, 1))
def run_richards(num_nodes): #Construct the data given a solution K = np.array([[1, 0], [0, 1]]) x = sym.Symbol('x') y = sym.Symbol('y') t = sym.Symbol('t') p = sym.Symbol('p') u_exact = -0.1 * sym.sin(math.pi * x) * sym.sin(math.pi * y) * t**2 - 1 # u_exact = -(t)**2*(x*y*(1-x)*(1-y))**2 - 1 # u_exact = (t**2*sym.cos(y*math.pi)*sym.cosh(x*math.pi))/12-1 K = p**2 theta = 1 / (1 - p) # theta = p f = sym.diff(theta.subs(p, u_exact), t) - divergence( gradient(u_exact, [x, y]), [x, y], K.subs(p, u_exact)) # f = sym.diff(u_exact,t)-divergence(gradient(u_exact ,[x,y]),[x,y]) f = sym.lambdify([x, y, t], f) u_exact = sym.lambdify([x, y, t], u_exact) #Define the mesh def random_perturbation(h, aspect): return lambda p: np.array([ random.uniform(0, h) * random.choice([-1, 1]) + p[0] - 0.5 * p[1], (1 / aspect) * random.uniform(0, h) * random.choice([-1, 1]) + p[1] ]) T = lambda p: np.array([p[0] + 0.5 * p[1], p[1]]) nx = num_nodes ny = num_nodes mesh = Mesh(nx, ny, T, ghostboundary=True) h = mesh.max_h() timestep = h**2 #cfl condition print('h ', h) #make mass and gravitation matrices mass = mass_matrix(mesh, sparse=True) #gravitation = gravitation_matrix(mesh) def compute_error(mesh, u, u_fabric): cx = mesh.cell_centers.shape[1] cy = mesh.cell_centers.shape[0] u_fabric_vec = u.copy() volumes = u.copy() for i in range(cy): for j in range(cx): u_fabric_vec[mesh.meshToVec(i, j)] = u_fabric( mesh.cell_centers[i, j, 0], mesh.cell_centers[i, j, 1]) volumes[mesh.meshToVec(i, j)] = mesh.volumes[i, j] L2err = math.sqrt( np.square(u - u_fabric_vec).T @ volumes / (np.ones(volumes.shape).T @ volumes)) maxerr = np.max(np.abs(u - u_fabric_vec)) return (L2err, maxerr) #Time discretization time_partition = np.linspace(0, 1, math.ceil(1 / timestep)) tau = time_partition[1] - time_partition[0] L = 0.5 TOL = 0.000000005 K = lambda x: x**2 theta = lambda x: 1 / (1 - x) # theta = lambda x:x u = mesh.interpolate(lambda x, y: u_exact(x, y, 0)) #Initial condition def L_scheme(u_j, u_n, TOL, L, K, tau, F): A = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) rhs = L * mass @ u_j + mass @ theta(u_n) - mass @ theta(u_j) + tau * F permability = K( np.reshape( u_j, (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1]), order='F')) lhs = tau * stiffness(mesh, np.eye(2), A, k_global=permability) + L * mass u_j_n = np.linalg.solve(lhs, rhs) # print(np.linalg.norm(u_j_n-u_j)) if np.linalg.norm(u_j_n - u_j) > TOL + TOL * np.linalg.norm(u_j_n): return L_scheme( u_j_n, u_n, TOL, L, K, tau, compute_vector(mesh, lambda x, y: f(x, y, t), lambda x, y: u_exact(x, y, t))) else: return u_j_n # for t in time_partition[1:]: # u = L_scheme(u,u,TOL,L,K,tau,compute_vector(mesh,lambda x,y: f(x,y,t),lambda x,y:u_exact(x,y,t))) # mesh.plot_vector(u,'numerical solution') # mesh.plot_funtion(lambda x,y: u_exact(x,y,t),'exact solution') # e = u - mesh.interpolate(lambda x,y: u_exact(x,y,t)) # mesh.plot_vector(e,'error') # print(t) # (l2,m) = compute_error(mesh,u,lambda x,y:u_exact(x,y,t)) # print(l2) # print(m) for t in time_partition[1:]: source = compute_vector(mesh, lambda x, y: f(x, y, t), lambda x, y: u_exact(x, y, t)) A = lil_matrix((mesh.num_unknowns, mesh.num_unknowns)) permability = K( np.reshape( u.copy(), (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1]), order='F')) # permability = np.ones((mesh.cell_centers.shape[0],mesh.cell_centers.shape[1]),order='F') A = stiffness(mesh, np.eye(2), A, k_global=permability) A = csr_matrix(A, dtype=float) #A = np.zeros((mesh.num_unknowns,mesh.num_unknowns)) rhs = tau * source + L * mass @ u lhs = tau * A + L * mass u_n_i = spsolve(lhs, rhs) # u_n_i = np.reshape(u_n_i,(mesh.cell_centers.shape[0],mesh.cell_centers.shape[1])) # u_n_i = np.ravel(u_n_i,order='F') u_n = u while np.linalg.norm(u_n_i - u_n) > TOL + TOL * np.linalg.norm(u_n): u_n = u_n_i A = lil_matrix((mesh.num_unknowns, mesh.num_unknowns)) permability = K( np.reshape( u_n.copy(), (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1]), order='F')) # permability = np.ones((mesh.cell_centers.shape[0],mesh.cell_centers.shape[1]),order='F') A = stiffness(mesh, np.eye(2), A, k_global=permability) A = csr_matrix(A, dtype=float) lhs = tau * A + L * mass rhs = -mass @ theta(u_n) + mass @ theta( u) + tau * source + L * mass @ u_n u_n_i = spsolve(lhs, rhs) # u_n_i = np.reshape(u_n_i,(mesh.cell_centers.shape[0],mesh.cell_centers.shape[1])) # u_n_i = np.ravel(u_n_i,order='F') u = u_n_i # mesh.plot_vector(u,'numerical solution') # mesh.plot_funtion(lambda x,y: u_exact(x,y,t),'exact solution') # e = u - mesh.interpolate(lambda x,y: u_exact(x,y,t)) # mesh.plot_vector(e,'error') # print(t) # (l2,m) = compute_error(mesh,u,lambda x,y:u_exact(x,y,t)) # print(l2) # print(m) return ((h, timestep), compute_error(mesh, u, lambda x, y: u_exact(x, y, 1)))
from scipy.sparse import csr_matrix,lil_matrix from scipy.sparse.linalg import spsolve import time as time K = np.array([[1,0],[0,1]]) transform = np.array([[1,0],[0.1,1]]) nx = 12 ny = 12 x = sym.Symbol('x') y = sym.Symbol('y') u_fabric = sym.cos(y*math.pi)*sym.cosh(x*math.pi) #u_fabric = (x*y*(1-x)*(1-y)) source = -divergence(gradient(u_fabric,[x,y]),[x,y],permability_tensor=K) print(source) source = sym.lambdify([x,y],source) u_lam = sym.lambdify([x,y],u_fabric) #T = lambda x,y: (0.9*y+0.1)*math.sqrt(x) + (0.9-0.9*y)*x**2 #T = lambda p: np.array([p[0]*0.1*p[1]+p[0],p[1]+p[1]*0.1*p[0]]) T = lambda p: np.array([p[0],p[1]]) def random_perturbation(h): return lambda p: np.array([random.uniform(0,h)*random.choice([-1,1]) + p[0] - 0.32*p[1],random.uniform(0,h)*random.choice([-1,1]) + p[1]]) mesh = Mesh(6,6,random_perturbation(1/20))
def elliptic(n): K = np.array([[1, 0], [0, 1]]) x = sym.Symbol('x') y = sym.Symbol('y') k = sym.Piecewise((0.1, x < 2 * y), (10, x >= 2 * y)) # k = (sym.sin(math.pi*x)*sym.sin(math.pi*y))+1.5 u_exact = -x * y * (1 - x) * (1 - y) - 1 # u_exact = sym.cos(y*math.pi)*sym.cosh(x*math.pi) f = -divergence(gradient(u_exact, [x, y]), [x, y], k) f = sym.lambdify([x, y], f) u_exact = sym.lambdify([x, y], u_exact) T = lambda p: np.array([p[0] - 0.5 * p[1] + 0.4 * p[1]**2, p[1]]) #T = lambda p: np.array([p[0]-0.5*p[1],p[1]]) def random_perturbation(h, aspect): return lambda p: np.array([ random.uniform(0, h) * random.choice([-1, 1]) + p[0] - 0.5 * p[1], (1 / aspect) * random.uniform(0, h) * random.choice([-1, 1]) + p[1] ]) T2 = random_perturbation(1 / (4 * n), 1) mesh = Mesh(n, n, T, centers_at_bc=True) mesh.plot() # mesh.plot_funtion(f,'source') k = sym.lambdify([x, y], k) k = mesh.interpolate(k) problem = k.copy() k = np.ones(k.shape[0]) * 0.1 #k = np.random.random(k.shape[0])*0.001 #k[1:50:4] = 10 permability = np.reshape( k, (mesh.midpoints.shape[0], mesh.midpoints.shape[1]), order='F') #permability[2:6,14:19] = 0.1 A = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) A = compute_matrix(mesh, K, A, k_global=permability) for i, row in enumerate(A): points = len(list(filter(lambda x: abs(x) > 0, row))) if points > 7: print(points, ' at ', mesh.vecToMesh(i)) problem[i] = 13 F = compute_vector(mesh, f, u_exact) u = np.linalg.solve(A, F) # Af = np.zeros((mesh.num_unknowns,mesh.num_unknowns)) # Af = compute_matrix_FEM(mesh,K,Af,k_global = permability) # Ff = compute_vector_FEM(mesh,f,u_exact) # uf = np.linalg.solve(Af,Ff) u = np.reshape(u, (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1])) u = np.ravel(u, order='F') # mesh.plot_vector(u,'FEM') # mesh.plot_funtion(u_exact,'excact') # e = u-mesh.interpolate(u_exact) # mesh.plot_vector(e,'error') # mesh.plot_vector(uf,'FEM') # mesh.plot_vector(uf-u,'difference') return compute_error(mesh, u, u_exact)