def tridiagonal_approach(): epsilon, alpha, beta = .02, 2., 4. # N = number of subintervals or finite elements def AnalyticSolution(x,alpha, beta,epsilon): out = alpha+x+(beta-alpha-1.)*(np.exp(x/epsilon) -1.)/(np.exp(1./epsilon) -1.) return out def matrix_diagonals(N): x = np.linspace(0,1,N+1)**(1.) # N+1 = number of grid points h = np.diff(x) b, f = np.zeros(N+1), np.zeros(N+1) a, c= np.zeros(N), np.zeros(N) b[0], b[N] = 1., 1. f[0], f[N] = alpha, beta # i = 0 to N-2 b[1:N] = -epsilon*(1./h[0:N-1] + 1./h[1:N]) f[1:N] = -.5*(h[0:N-1] + h[1:N]) c[1:N] = epsilon/h[1:N] - .5 a[0:N-1] = epsilon/h[0:N-1] + .5 return a, b, c, f, x n = [2**i for i in range(4,22)] max_error_fe = [10]*(len(n)) h = [1./num for num in n] for j in range(len(n)): a, b, c, f, x = matrix_diagonals(n[j]) numerical_soln = tridiag(a,b,c,f) analytic_soln = AnalyticSolution(x, alpha, beta,epsilon) max_error_fe[j] = np.max(np.abs(numerical_soln - analytic_soln)) #print "max_error = ", max_error_fe plt.loglog(n,max_error_fe,'-k',linewidth=2.) plt.show() N = 500 a, b, c, f, x = matrix_diagonals(N) numerical_soln = tridiag(a,b,c,f) epsilon = .02 analytic_soln = AnalyticSolution(x,alpha, beta,epsilon) #print "Error = ", np.max(np.abs(numerical_soln- analytic_soln)) # plt.plot(x,numerical_soln,'-*r',lw=2.) plt.plot(x,analytic_soln,'-k',lw=2.) plt.savefig("FEM_singular_solution.pdf") plt.clf()
def tridiagonal_approach(): epsilon, alpha, beta = .02, 2., 4. # N = number of subintervals or finite elements def AnalyticSolution(x, alpha, beta, epsilon): out = alpha + x + (beta - alpha - 1.) * (np.exp(x / epsilon) - 1.) / ( np.exp(1. / epsilon) - 1.) return out def matrix_diagonals(N): x = np.linspace(0, 1, N + 1)**(1.) # N+1 = number of grid points h = np.diff(x) b, f = np.zeros(N + 1), np.zeros(N + 1) a, c = np.zeros(N), np.zeros(N) b[0], b[N] = 1., 1. f[0], f[N] = alpha, beta # i = 0 to N-2 b[1:N] = -epsilon * (1. / h[0:N - 1] + 1. / h[1:N]) f[1:N] = -.5 * (h[0:N - 1] + h[1:N]) c[1:N] = epsilon / h[1:N] - .5 a[0:N - 1] = epsilon / h[0:N - 1] + .5 return a, b, c, f, x n = [2**i for i in range(4, 22)] max_error_fe = [10] * (len(n)) h = [1. / num for num in n] for j in range(len(n)): a, b, c, f, x = matrix_diagonals(n[j]) numerical_soln = tridiag(a, b, c, f) analytic_soln = AnalyticSolution(x, alpha, beta, epsilon) max_error_fe[j] = np.max(np.abs(numerical_soln - analytic_soln)) #print "max_error = ", max_error_fe plt.loglog(n, max_error_fe, '-k', linewidth=2.) plt.show() N = 500 a, b, c, f, x = matrix_diagonals(N) numerical_soln = tridiag(a, b, c, f) epsilon = .02 analytic_soln = AnalyticSolution(x, alpha, beta, epsilon) #print "Error = ", np.max(np.abs(numerical_soln- analytic_soln)) # plt.plot(x,numerical_soln,'-*r',lw=2.) plt.plot(x, analytic_soln, '-k', lw=2.) plt.savefig("FEM_singular_solution.pdf") plt.clf()
def _one_pop_const_params_X(phi, xx, T, nu=1, gamma=0, h=0.5, beta=1, alpha=1, theta0=1, initial_t=0): """ Integrate one population with constant parameters. In this case, we can precompute our a,b,c matrices for the linear system we need to evolve. This we can efficiently do in Python, rather than relying on C. The nice thing is that the Python is much faster to debug. """ if numpy.any(numpy.less([T, nu, theta0, beta, alpha], 0)): raise ValueError('A time, population size, migration rate, theta0, ' 'beta, or alpha is < 0. Has the model been ' 'mis-specified?') if numpy.any(numpy.equal([nu, beta], 0)): raise ValueError('A population size or beta is 0. Has the model been ' 'mis-specified?') M = _Mfunc1D_X(xx, gamma, h, beta) MInt = _Mfunc1D_X((xx[:-1] + xx[1:]) / 2, gamma, h, beta) V = _Vfunc_X(xx, nu, beta) VInt = _Vfunc_X((xx[:-1] + xx[1:]) / 2, nu, beta) dx = numpy.diff(xx) dfactor = _compute_dfactor(dx) delj = _compute_delj(dx, MInt, VInt) a = numpy.zeros(phi.shape) a[1:] += dfactor[1:] * (-MInt * delj - V[:-1] / (2 * dx)) c = numpy.zeros(phi.shape) c[:-1] += -dfactor[:-1] * (-MInt * (1 - delj) + V[1:] / (2 * dx)) b = numpy.zeros(phi.shape) b[:-1] += -dfactor[:-1] * (-MInt * delj - V[:-1] / (2 * dx)) b[1:] += dfactor[1:] * (-MInt * (1 - delj) + V[1:] / (2 * dx)) if (M[0] <= 0): b[0] += (0.5 / nu - M[0]) * 2 / dx[0] if (M[-1] >= 0): b[-1] += -(-0.5 / nu - M[-1]) * 2 / dx[-1] dt = _compute_dt(dx, nu, [0], gamma, h) current_t = initial_t while current_t < T: this_dt = min(dt, T - current_t) _inject_mutations_1D_X(phi, this_dt, xx, theta0, beta, alpha) r = phi / this_dt phi = tridiag.tridiag(a, b + 1. / this_dt, c, r) current_t += this_dt return phi
def tridiagonal_approach(): epsilon, alpha, beta = .02, 2., 4. # N = number of subintervals or finite elements def AnalyticSolution(x,alpha, beta,epsilon): out = alpha+x+(beta-alpha-1.)*(np.exp(x/epsilon) -1.)/(np.exp(1./epsilon) -1.) return out def matrix_diagonals(N): x = np.linspace(0,1,N+1)**(1.) # N+1 = number of grid points h = np.diff(x) b, f = np.zeros(N+1), np.zeros(N+1) a, c= np.zeros(N), np.zeros(N) b[0], b[N] = 1., 1. f[0], f[N] = alpha, beta # i = 0 to N-2 b[1:N] = -epsilon*(1./h[0:N-1] + 1./h[1:N]) f[1:N] = -.5*(h[0:N-1] + h[1:N]) c[1:N] = epsilon/h[1:N] - .5 a[0:N-1] = epsilon/h[0:N-1] + .5 return a, b, c, f, x n = [2**i for i in range(4,22)] max_error_fe = [10]*(len(n)) h = [1./num for num in n] for j in range(len(n)): a, b, c, f, x = matrix_diagonals(n[j]) numerical_soln = tridiag(a,b,c,f) analytic_soln = AnalyticSolution(x, alpha, beta,epsilon) max_error_fe[j] = np.max(np.abs(numerical_soln - analytic_soln)) n2 = [2*i for i in range(4,50)] max_error_cheb = [10]*len(n2) for j in range(len(n2)): N = n2[j] D,x = cheb(N) M = 4*epsilon*D.dot(D) -2.*D M[0] = 0. M[-1] = 0. M[0,0] = 1. M[-1,-1] = 1. F = -np.ones(len(x)) F[0] = 4 # beta F[-1] = 2 # alpha cheb_sol = solve(M,F) analytic_soln = AnalyticSolution((x+1.)/2., alpha, beta,epsilon) max_error_cheb[j] = np.max(np.abs(cheb_sol - analytic_soln)) plt.loglog(n2,max_error_cheb,'-b',linewidth=2.,label='Chebychev Error') plt.loglog(n,max_error_fe,'-k',linewidth=2.) plt.xlabel('$n$',fontsize=16) plt.ylabel('$E(n)$',fontsize=16) # plt.savefig("FEM_error_2nd_order.pdf") plt.show() plt.clf()
def poisson(n): '''Returns a sparse square coefficient matrix for the 1D Poisson equation. ''' import scipy.sparse as sparse from tridiag import tridiag s = tridiag(n, -1, 2, -1) i = sparse.eye(n, n) A = s + i * 2.0 return A
def _one_pop_const_params_X(phi, xx, T, nu=1, gamma=0, h=0.5, beta=1, alpha=1, theta0=1, initial_t=0): """ Integrate one population with constant parameters. In this case, we can precompute our a,b,c matrices for the linear system we need to evolve. This we can efficiently do in Python, rather than relying on C. The nice thing is that the Python is much faster to debug. """ if numpy.any(numpy.less([T,nu,theta0,beta,alpha], 0)): raise ValueError('A time, population size, migration rate, theta0, ' 'beta, or alpha is < 0. Has the model been ' 'mis-specified?') if numpy.any(numpy.equal([nu,beta], 0)): raise ValueError('A population size or beta is 0. Has the model been ' 'mis-specified?') M = _Mfunc1D_X(xx, gamma, h, beta) MInt = _Mfunc1D_X((xx[:-1] + xx[1:])/2, gamma, h, beta) V = _Vfunc_X(xx, nu, beta) VInt = _Vfunc_X((xx[:-1] + xx[1:])/2, nu, beta) dx = numpy.diff(xx) dfactor = _compute_dfactor(dx) delj = _compute_delj(dx, MInt, VInt) a = numpy.zeros(phi.shape) a[1:] += dfactor[1:]*(-MInt * delj - V[:-1]/(2*dx)) c = numpy.zeros(phi.shape) c[:-1] += -dfactor[:-1]*(-MInt * (1-delj) + V[1:]/(2*dx)) b = numpy.zeros(phi.shape) b[:-1] += -dfactor[:-1]*(-MInt * delj - V[:-1]/(2*dx)) b[1:] += dfactor[1:]*(-MInt * (1-delj) + V[1:]/(2*dx)) if(M[0] <= 0): b[0] += (0.5/nu - M[0])*2/dx[0] if(M[-1] >= 0): b[-1] += -(-0.5/nu - M[-1])*2/dx[-1] dt = _compute_dt(dx,nu,[0],gamma,h) current_t = initial_t while current_t < T: this_dt = min(dt, T - current_t) _inject_mutations_1D_X(phi, this_dt, xx, theta0, beta, alpha) r = phi/this_dt phi = tridiag.tridiag(a, b+1./this_dt, c, r) current_t += this_dt return phi
def tridiagonal_approach(): epsilon, alpha, beta = .02, 2., 4. # N = number of subintervals or finite elements def AnalyticSolution(x, alpha, beta, epsilon): out = alpha + x + (beta - alpha - 1.) * (np.exp(x / epsilon) - 1.) / ( np.exp(1. / epsilon) - 1.) return out def matrix_diagonals(N): x = np.linspace(0, 1, N + 1)**(1.) # N+1 = number of grid points h = np.diff(x) b, f = np.zeros(N + 1), np.zeros(N + 1) a, c = np.zeros(N), np.zeros(N) b[0], b[N] = 1., 1. f[0], f[N] = alpha, beta # i = 0 to N-2 b[1:N] = -epsilon * (1. / h[0:N - 1] + 1. / h[1:N]) f[1:N] = -.5 * (h[0:N - 1] + h[1:N]) c[1:N] = epsilon / h[1:N] - .5 a[0:N - 1] = epsilon / h[0:N - 1] + .5 return a, b, c, f, x n = [2**i for i in range(4, 22)] max_error_fe = [10] * (len(n)) h = [1. / num for num in n] for j in range(len(n)): a, b, c, f, x = matrix_diagonals(n[j]) numerical_soln = tridiag(a, b, c, f) analytic_soln = AnalyticSolution(x, alpha, beta, epsilon) max_error_fe[j] = np.max(np.abs(numerical_soln - analytic_soln)) n2 = [2 * i for i in range(4, 50)] max_error_cheb = [10] * len(n2) for j in range(len(n2)): N = n2[j] D, x = cheb(N) M = 4 * epsilon * D.dot(D) - 2. * D M[0] = 0. M[-1] = 0. M[0, 0] = 1. M[-1, -1] = 1. F = -np.ones(len(x)) F[0] = 4 # beta F[-1] = 2 # alpha cheb_sol = solve(M, F) analytic_soln = AnalyticSolution((x + 1.) / 2., alpha, beta, epsilon) max_error_cheb[j] = np.max(np.abs(cheb_sol - analytic_soln)) plt.loglog(n2, max_error_cheb, '-b', linewidth=2., label='Chebychev Error') plt.loglog(n, max_error_fe, '-k', linewidth=2.) plt.xlabel('$n$', fontsize=16) plt.ylabel('$E(n)$', fontsize=16) # plt.savefig("FEM_error_2nd_order.pdf") plt.show() plt.clf()