Buckets:
| from varform1D import * | |
| import sympy as sym | |
| import numpy as np | |
| def phi_factory(name, N, highest_derivative=2): | |
| """ | |
| Generate N+1 basis functions (phi) on [0,1] which vanish | |
| on the boundary. Differentiate the functions up to | |
| (and including) highest_derivative. | |
| """ | |
| x = sym.Symbol('x') | |
| from sympy import sin, cos, pi | |
| if name == 'sines': | |
| phi = {0: [sin(pi*(i+1)*x) for i in range(N+1)]} | |
| elif name == 'poly': | |
| phi = {0: [x**(i+1)*(1-x) for i in range(N+1)]} | |
| elif name == 'poly2': | |
| phi = {0: [x**(i+2)*(1-x) for i in range(N+1)]} | |
| elif name == 'poly3': | |
| phi = {0: [(1-x)**(i+1) for i in range(N+1)]} | |
| elif name == 'Lagrange': | |
| from Lagrange import Lagrange_polynomials | |
| # Return all Lagrange polynomials and strip off | |
| # boundary polynomials in application code (if necessary) | |
| phi = {0: Lagrange_polynomials(x, N, [0,1], 'uniform')[0]} | |
| elif name == 'Lagrange_Cheb': | |
| from Lagrange import Lagrange_polynomials | |
| phi = {0: Lagrange_polynomials(x, N, [0,1], 'Chebyshev')} | |
| # Compute derivatives of the basis functions | |
| for d in range(1, highest_derivative+1): | |
| phi[d] = [sym.diff(phi[0][i], x, d) for i in range(len(phi[0]))] | |
| return phi | |
| def case0(f, N=3): | |
| B = 1 - x**3 | |
| dBdx = sym.diff(B, x) | |
| # Compute basis functions and their derivatives | |
| phi = {0: [x**(i+1)*(1-x) for i in range(N+1)]} | |
| phi[1] = [sym.diff(phi_i, x) for phi_i in phi[0]] | |
| def integrand_lhs(phi, i, j): | |
| return phi[1][i]*phi[1][j] | |
| def integrand_rhs(phi, i): | |
| return f*phi[0][i] - dBdx*phi[1][i] | |
| Omega = [0, 1] | |
| u_bar = solve(integrand_lhs, integrand_rhs, phi, Omega, | |
| verbose=True, symbolic=True) | |
| u = B + u_bar | |
| print 'solution u:', sym.simplify(sym.expand(u)) | |
| # Calculate analytical solution | |
| # Solve -u''=f by integrating f twice | |
| f1 = sym.integrate(f, x) | |
| f2 = sym.integrate(f1, x) | |
| # Add integration constants | |
| C1, C2 = sym.symbols('C1 C2') | |
| u_e = -f2 + C1*x + C2 | |
| # Find C1 and C2 from the boundary conditions u(0)=0, u(1)=1 | |
| s = sym.solve([u_e.subs(x,0) - 1, u_e.subs(x,1) - 0], [C1, C2]) | |
| # Form the exact solution | |
| u_e = -f2 + s[C1]*x + s[C2] | |
| print 'analytical solution:', u_e | |
| #print 'error:', u - u_e # many terms - which cancel | |
| print 'error:', sym.expand(u - u_e) | |
| def case1(N, basis='sines'): | |
| """ | |
| Solve -u''=f(x) on [0,1], u(0)=u(1)=0. f(x)=2. | |
| Method: least-squares, Galerkin, collocation. | |
| """ | |
| f = 2 | |
| D = 0; L = 1 | |
| def integrand_lhs_LS(phi, i, j): | |
| return -phi[2][i]*phi[2][j] | |
| def integrand_rhs_LS(phi, i): | |
| return f*phi[2][i] | |
| def integrand_lhs_G2(phi, i, j): | |
| return -phi[0][i]*phi[2][j] | |
| def integrand_rhs_G2(phi, i): | |
| return f*phi[0][i] | |
| def integrand_lhs_G1(phi, i, j): | |
| return phi[1][i]*phi[1][j] | |
| def integrand_rhs_G1(phi, i): | |
| return f*phi[0][i] | |
| def term_lhs_co(phi, x, i, j): | |
| return -phi[2][j](x[i]) | |
| def term_rhs_co(phi, x, i): | |
| return 2 | |
| Omega = [0, 1] | |
| phi = phi_factory(basis, N, 2) | |
| u = {} # dict of solutions corresponding to different methods | |
| u['LS'] = solve(integrand_lhs_LS, integrand_rhs_LS, phi, Omega) | |
| u['G1'] = solve(integrand_lhs_G1, integrand_rhs_G1, phi, Omega) | |
| u['G2'] = solve(integrand_lhs_G2, integrand_rhs_G2, phi, Omega) | |
| u['exact'] = x*(D + L - x) | |
| # Test different collocation points | |
| points = [] | |
| if N == 0: | |
| points.extend([sym.Rational(1,2), 0.1, 0.9]) | |
| else: | |
| points.append(np.linspace(0.1, 0.9, N+1)) # uniformly distributed | |
| for seed in 2, 10: | |
| np.random.seed(seed) | |
| points.append(np.random.uniform(0, 1, size=N+1)) | |
| for k, p in enumerate(points): | |
| u['co'+str(k)] = collocation(term_lhs_co, term_rhs_co, phi, p) | |
| import pprint; pprint.pprint(u) | |
| comparison_plot(u, [0, 1]) | |
| def case2(N): | |
| """ | |
| Solve -u''=f(x) on [0,1], u'(0)=C, u(1)=D. | |
| Method: Galerkin only. | |
| """ | |
| x = sym.Symbol('x') | |
| f = 2 | |
| D = 2; E = 3; | |
| L = 1 # basis function factory restricted to [0,1] | |
| D = sym.Symbol('D') | |
| C = sym.Symbol('C') | |
| # u exact | |
| f1 = sym.integrate(f, x) | |
| f2 = sym.integrate(f1, x) | |
| C1, C2 = sym.symbols('C1 C2') | |
| u = -f2 + C1*x + C2 | |
| BC1 = sym.diff(u,x).subs(x, 0) - C | |
| BC2 = u.subs(x,1) - D | |
| s = sym.solve([BC1, BC2], [C1, C2]) | |
| u_e = -f2 + s[C1]*x + s[C2] | |
| def diff_eq(u, x): | |
| eqs = {'diff': -sym.diff(u, x, x) - f, | |
| 'BC1': sym.diff(u, x).subs(x, 0) - C, | |
| 'BC2': u.subs(x, L) - D} | |
| for eq in eqs: | |
| eqs[eq] = sym.simplify(eqs[eq]) | |
| print 'Check of exact solution:', diff_eq(u_e, x) | |
| def integrand_lhs(phi, i, j): | |
| return phi[1][i]*phi[1][j] | |
| B = D*x/L | |
| dBdx = sym.diff(B, x) | |
| def integrand_rhs(phi, i): | |
| return f*phi[0][i] - dBdx*phi[1][i] | |
| boundary_lhs = None # not used here | |
| def boundary_rhs(phi, i): | |
| return -C*phi[0][i].subs(x, 0) | |
| Omega = [0, L] | |
| phi = phi_factory('poly3', N, 1) | |
| #phi = phi_factory('Lagrange', N, 1) | |
| print phi[0] | |
| u = {'G1': solve(integrand_lhs, integrand_rhs, phi, Omega, | |
| boundary_lhs, boundary_rhs, verbose=True) + B, | |
| 'exact': u_e} | |
| print 'numerical solution:', u['G1'] | |
| print 'simplified:', sym.simplify(u['G1']) | |
| print 'u exact', u['exact'] | |
| # Change from symblic to numerical computing for plotting. | |
| # That is, replace C and D symbols by numbers | |
| # (comparison_plot takes the expressions with x to functions of x | |
| # so C and D must have numbers). | |
| for name in u: | |
| u[name] = u[name].subs(C, 2).subs(D, -2) | |
| print 'u:', u | |
| C = 2; D = -2 # Note that these are also remembered by u_e | |
| comparison_plot(u, [0, 1]) | |
| def case3(N, a=1, a_symbols={}, f=0, f_symbols={}, | |
| basis='poly', symbolic=True, B_type='linear'): | |
| """ | |
| Solve -(a(x)u)'=0 on [0,1], u(0)=1, u(1)=0. | |
| Method: Galerkin. | |
| a and f must be sympy expressions with x as the only symbol | |
| (other symbols in a gives very long symbolic expressions in | |
| the solution and is of little value). | |
| """ | |
| # Note: a(x) with symbols | |
| #f = sym.Rational(10,7) # for a=1, corresponds to f=0 when a=1/(2+10x) | |
| """ | |
| def a(x): # very slow | |
| return sym.Piecewise((a1, x < sym.Rational(1,2)), | |
| (a2, x >= sym.Rational(1,2))) | |
| def a(x): # cannot be treated by sympy or wolframalpha.com | |
| return 1./(a1 + a2*x) | |
| # Symbolic a(x) makes large expressions... | |
| def a(x): | |
| return 2 + b*x | |
| def a(x): | |
| return 1/(2 + b*x) | |
| def a(x): | |
| return 1/(2 + 10*x) | |
| b = sym.Symbol('b') | |
| def a(x): | |
| return sym.exp(b*x) | |
| """ | |
| if f == 0: | |
| h = sym.integrate(1/a, x) | |
| h1 = h.subs(x, 1) | |
| h0 = h.subs(x, 0) | |
| u_exact = 1 - (h-h0)/(h1-h0) | |
| else: | |
| # Assume a=1 | |
| f1 = sym.integrate(f, x) | |
| f2 = sym.integrate(f1, x) | |
| C1, C2 = sym.symbols('C1 C2') | |
| u = -f2 + C1*x + C2 | |
| BC1 = u.subs(x,0) - 1 | |
| BC2 = u.subs(x,1) - 0 | |
| s = sym.solve([BC1, BC2], [C1, C2]) | |
| u_exact = -f2 + s[C1]*x + s[C2] | |
| print 'u_exact:', u_exact | |
| def integrand_lhs(phi, i, j): | |
| return a*phi[1][i]*phi[1][j] | |
| def integrand_rhs(phi, i): | |
| return f*phi[0][i] - a*dBdx*phi[1][i] | |
| boundary_lhs = boundary_rhs = None # not used here | |
| Omega = [0, 1] | |
| if B_type == 'linear': | |
| B = 1 - x | |
| elif B_type == 'cubic': | |
| B = 1 - x**3 | |
| elif B_type == 'sqrt': | |
| B = 1 - sym.sqrt(x) | |
| else: | |
| B = 1 - x | |
| if basis == 'poly': | |
| phi = phi_factory('poly', N, 1) | |
| elif basis == 'Lagrange': | |
| phi = phi_factory('Lagrange', N, 1) | |
| print 'len phi:', len(phi) | |
| B = phi[0][0]*1 + phi[0][-1]*0 | |
| phi[0] = phi[0][1:-1] | |
| phi[1] = phi[1][1:-1] | |
| elif basis == 'sines': | |
| phi = phi_factory('sines', N, 1) | |
| else: | |
| raise ValueError('basis=%s must be poly, Lagrange or sines' % basis) | |
| print 'Basis functions:', phi[0] | |
| dBdx = sym.diff(B, x) | |
| verbose = True if symbolic else False | |
| phi_sum = solve(integrand_lhs, integrand_rhs, phi, Omega, | |
| boundary_lhs, boundary_rhs, verbose=verbose, | |
| symbolic=symbolic) | |
| print 'sum c_j*phi_j:', phi_sum | |
| name = 'numerical, N=%d' % N | |
| u = {name: phi_sum + B, 'exact': sym.simplify(u_exact)} | |
| print 'Numerical solution:', u[name] | |
| if verbose: | |
| print '...simplified to', sym.simplify(u[name]) | |
| print '...exact solution:', sym.simplify(u['exact']) | |
| f_str = str(f).replace(' ', '') | |
| a_str = str(a).replace(' ', '') | |
| filename = 'DaDu=-%s_a=%s_N%s_%s.eps' % (f_str, a_str, N, basis) | |
| # Change from symblic to numerical computing for plotting. | |
| all_symbols = {} | |
| all_symbols.update(a_symbols) | |
| all_symbols.update(f_symbols) | |
| if all_symbols: | |
| for s in all_symbols: | |
| value = all_symbols[s] | |
| print 'symbol', s, 'gets value', value | |
| u[name] = u[name].subs(s, value) | |
| u['exact'] = u['exact'].subs(s, value) | |
| print 'Numerical u_exact formula before plot:', u_exact | |
| comparison_plot(u, [0, 1], filename) | |
| def comparison_plot(u, Omega, filename='tmp.eps'): | |
| """ | |
| Plot the solution u(x) (a sympy expression with x as the only | |
| symbol - all other symbols must have been substituted by numbers) | |
| and the exact solution u_e (which is a Python function that can | |
| take an array x and return the values of the exact solution). | |
| Omega is a 2-tuple/list with the domain's lower and upper limit. | |
| """ | |
| x = sym.Symbol('x') | |
| resolution = 401 | |
| xcoor = np.linspace(Omega[0], Omega[1], resolution) | |
| for name in u: | |
| u[name] = sym.lambdify([x], u[name], modules="numpy") | |
| u[name] = u[name](xcoor) | |
| legends = [] | |
| for name in u: | |
| plot(xcoor, u[name]) | |
| hold('on') | |
| legends.append(name) | |
| legend(legends) | |
| savefig(filename) | |
| x, b = sym.symbols('x b') | |
| #case1(8, 'sines') | |
| #case2(1) | |
| #case3(4) | |
| #case3(N=3, a=sym.exp(b*x), f=0, basis='poly', | |
| # a_symbols={b: 8}, f_symbols={}) | |
| #case3(N=2, a=1, f=b, basis='poly', f_symbols={b: 10}, B_type='cubic') | |
| #case0(f=b, N=1) | |
| #case0(f=x**6, N=7) | |
| case2(1) | |
Xet Storage Details
- Size:
- 10.4 kB
- Xet hash:
- e47470faae7a71107d9f482343fd1dea5477a9dd658b7c7aa2bbb5635738bd12
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.