def newton_multi_var(functions, x0, tol=0.001): """ Calculate one the roots of the simultaneous equations represented by functions Args: functions (array of (array of floats->float)): This is a list of functions, each of which takes a vector x and outputs a float. For example: if it is wanted to solve the simultaneous equations: x_1 ** 2 + x_1 * x_2 - 10 = 0 x_2 + 3 * x_1 * x_2 ** 2 - 57 = 0 def function1(x): return x[0] ** 2 + x[0] * x[1] - 10 def function2(x): return x[1] + 3 * x[0] * x[1] ** 2 - 57 functions = [function1, function2] However, the initial guess x0 is an array where the first element is the guess for x_1 and the second element is the guess for x_2 x0 (array of floats): the initial guess tol: the tolerance of the estimated error Returns: (numpy column of floats): the estimated root. the i-th value corresponds to the i-th variable """ f = np.zeros((len(functions), 1)) J = np.zeros((len(functions), len(x0))) x0 = np.array(x0).reshape(len(x0), 1) x_new = x0.copy() x_old = x0.copy() error = x_new - x_new + 1.0 + tol while ((np.fabs(error) >= tol).any()): for i in range(len(functions)): f[i][0] = functions[i](x_old) J[i, :] = gradient(functions[i], x_old) x_new = np.linalg.solve(J, -f + J @ x_old.reshape(len(x_old), 1)) error = np.abs(x_new - x_old) / x_new * 100.0 x_old = x_new return x_new
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 gradient_descend(func, x_0, tol=0.001, gamma=0.1, beta=0.90): """ Estimates the value of the local minimum of the multivariable function func near x_0 func (array of floats->float): the function that is going to be minimized x_0 (array of floats): the initial value/guess gamma (float (0, 1]: learning rate beta (float [0, 1]): momentum Returns: (numpy array of floats): the value of the independent variable that is estimated to locally minimizes func """ x_0 = np.array(x_0).reshape(len(x_0), ) current = x_0.copy() error = tol + 1.0 old_gradient = current * 0 while error >= tol: grad = gradient(func, current) current = current - gamma * (beta * old_gradient + (1.0 - beta) * grad) old_gradient = grad error = norm_euclidean(grad) return current
def examples_differentiation(): print("========== DIFFERENTIATION ==========") print("f(x) = x^3 - x^2 + x - 1 + e^(x) * cos(x)") print("df/dx at x=5 is 66 - e^5 (cos(5) - sin(5))") print("Or about 250.416182") print("Some estimates: ") def f(x): return x ** 3 - x ** 2 + x - 1 + np.exp(x) * np.cos(x) print(differentiation.first_derivative_backwards(f, 5.0)) print(differentiation.first_derivative_centered(f, 5.0)) print(differentiation.first_derivative_forward(f, 5.0)) print() print("The second derivative at x = 5 is 28 - 2e^5 sin(5)") print("Or about 312.6339619") print(differentiation.second_derivative_backwards(f, 5.0)) print(differentiation.second_derivative_centered(f, 5.0)) print(differentiation.second_derivative_forward(f, 5.0)) print() print("Third derivative: -2(-3 + e^5 sin(5) + e^5 cos(5))") print("About 206.4355598") print(differentiation.third_derivative_backward(f, 5.0)) print(differentiation.third_derivative_centered(f, 5.0)) print(differentiation.third_derivative_forward(f, 5.0)) print() print("Fourth derivative: -4e^5 cos(5)") print("About -168.3968049") print(differentiation.fourth_derivative_backward(f, 5.0)) print(differentiation.fourth_derivative_centered(f, 5.0)) print(differentiation.fourth_derivative_forward(f, 5.0)) print("\nNow using the API to get the nth derivative:") for i in range(1, 5, 1): print("Order: ", i) print(differentiation.deriv_n(f, 5.0, i, h=0.0008)) print("\nAlso works with lists: (evaluates derivative at each value from the vector)") t = np.linspace(0, 5, 6) print() for i in range(1, 5, 1): print("Derivative of order {} on {} is \n{}\n".format(i, t, differentiation.deriv_n(f, t, i))) print("\nNow more first order derivatives through various methods: ") print("\nRichardson extrapolation: ") print(differentiation.richardson_extrapolation(f, 5.0)) print("\nAlso works with lists: (evaluates derivative at each value from the vector)") print(differentiation.richardson_extrapolation(f, t)) print("\nThe same goes for romberg's method: ") print(differentiation.derivative_romberg(f, 5.0)) print(differentiation.derivative_romberg(f, t)) print() print("\nUsing lagrange polynomial: ") x = np.linspace(0.0, 10.0, 100) y = f(x) print(differentiation.derivative_lagrange_poly(x, y, 5.0)) print(differentiation.derivative_lagrange_poly(x, y, t)) print("\nWe can also differentiate multivariable functions") print("Let multi(x, y) = x ^ 2 * y") def multi(x): return x[0] ** 2 * x[1] print("We can take partial derivatives") print("x = 3.0, y = 2.0") print("\nPartial respect to x: ") print(differentiation.partialDerivative(multi, [3.0, 2.0], 0)) print("\nPartial respect to y: ") print(differentiation.partialDerivative(multi, [3.0, 2.0], 1)) print("\nAlso gradients: ") print(differentiation.gradient(multi, [3.0, 2.0])) print(differentiation.gradient_f(multi)([3.0, 2.0]))
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))
cell_centers[i, j, 1]) continue vector[meshToVec(i, j)] += mesh.volumes[i, j] * f( cell_centers[i, j, 0], cell_centers[i, j, 1]) return vector if __name__ == '__main__': import sympy as sym from differentiation import gradient, divergence import math x = sym.Symbol('x') y = sym.Symbol('y') K = np.array([[1, 0], [0, 1]]) u_fabric = sym.cos(y * math.pi) * sym.cosh(x * math.pi) source = -divergence(gradient(u_fabric, [x, y]), [x, y], permability_tensor=K) source = sym.lambdify([x, y], source) u_lam = sym.lambdify([x, y], u_fabric) mesh = Mesh(20, 20, lambda p: np.array([p[0], p[1]])) mesh.plot() A = np.zeros((mesh.num_unknowns, mesh.num_unknowns)) flux_matrix = { 'x': np.zeros((mesh.num_unknowns, mesh.num_unknowns)), 'y': np.zeros((mesh.num_unknowns, mesh.num_unknowns)) } permability = np.ones( (mesh.cell_centers.shape[0], mesh.cell_centers.shape[1])) permability[2:4, 16:19] = 0.1 A, fx, fy = compute_matrix(mesh, np.array([[1, 0], [0, 1]]), A,
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)