def solut(theta, D, nmax, N, wold): """ Method that sets up the tridiagonal implicitt scheme to be solved with tdma using an iteration process Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number nmax(int): number of timesteps N(int): number of equations wold(array): solution from previous iteration Returns: wnew(array): iterated solution at timestep nmax """ tmp1 = D*(1. - theta) for n in range(nmax): a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1,N): fac = 0.5 / (j + 1) a[j] = -D*theta*(1 - fac) b[j] = (1 + 2*D*theta) c[j] = -D*theta*(1 + fac) d[j] = tmp1*((1 - fac)*wold[j - 1] + (1 + fac)*wold[j + 1]) + (1 - 2*tmp1)*wold[j] b[0] = 1 + 4*D*theta/3 c[0] = -4*D*theta/3 d[0] = (1-4*tmp1/3.)*wold[0] + 4*tmp1*wold[1]/3. wnew = tdma(a, b, c, d) wold = np.append(wnew, [0]) return wnew
def solveAllTimestepsStartup(theta, D, nmax, N, wold): """ Method that sets up the tridiagonal theta-scheme for the startup of flow in a pipe (Szymanski's problem). The method solves without storing solutions from t0 to t = dt*nmax, using standard tdma solver. The Governing equation is: dw/dt = w'' + w'/r, w = w(r,t), 0 < r < 1 where w' denotes dw/dr. velocity field: u(r,t) = us(r) -w(r,t) where us = 1 - r^2 Boundary conditions: w^n+1(0) = (1-2D)w^n(1) + 4Du^n(1), w(r) = 0 Initial condition: w(r,0) = 1- r^2 = us Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number nmax(int): number of iterations N(int): number of equations wold(array): solution from previous iteration Returns: wnew(array): solution at time t = dt*nmax """ tmp1 = D * (1. - theta) for n in range(nmax): a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1, N): fac = 0.5 / (j) a[j] = -D * theta * (1 - fac) b[j] = (1 + 2 * D * theta) c[j] = -D * theta * (1 + fac) d[j] = tmp1 * ((1 - fac) * wold[j - 1] + (1 + fac) * wold[j + 1]) + (1 - 2 * tmp1) * wold[j] b[0] = 1 + 4 * D * theta c[0] = -4 * D * theta d[0] = wold[0] + 4 * tmp1 * (wold[1] - wold[0]) wnew = tdma(a, b, c, d) wold = np.append(wnew, [0]) return wold
def solveAllTimestepsStartup(theta, D, nmax, N, wold): """ Method that sets up the tridiagonal theta-scheme for the startup of flow in a pipe (Szymanski's problem). The method solves without storing solutions from t0 to t = dt*nmax, using standard tdma solver. The Governing equation is: dw/dt = w'' + w'/r, w = w(r,t), 0 < r < 1 where w' denotes dw/dr. velocity field: u(r,t) = us(r) -w(r,t) where us = 1 - r^2 Boundary conditions: w^n+1(0) = (1-2D)w^n(1) + 4Du^n(1), w(r) = 0 Initial condition: w(r,0) = 1- r^2 = us Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number nmax(int): number of iterations N(int): number of equations wold(array): solution from previous iteration Returns: wnew(array): solution at time t = dt*nmax """ tmp1 = D*(1. - theta) for n in range(nmax): a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1, N): fac = 0.5 / (j) a[j] = -D*theta*(1 - fac) b[j] = (1 + 2*D*theta) c[j] = -D*theta*(1 + fac) d[j] = tmp1*((1 - fac)*wold[j - 1] + (1 + fac)*wold[j + 1]) + (1 - 2*tmp1)*wold[j] b[0] = 1 + 4*D*theta c[0] = -4*D*theta d[0] = wold[0] + 4*tmp1*(wold[1] - wold[0]) wnew = tdma(a, b, c, d) wold = np.append(wnew, [0]) return wold
def solveNextTimestepStartupV2(theta, D, N, wold): """ Method that sets up the tridiagonal theta-scheme for the startup of flow in a pipe (Szymanski's problem). The method solves only for the next time-step, using standard tdma solver. The Governing equation is: dw/dt = w'' + w'/r, w = w(r,t), 0 < r < 1 where w' denotes dw/dr. velocity field: u(r,t) = us(r) -w(r,t) where us = 1 - r^2 Boundary conditions: w(0) = (4w(1)-w(2))/3), w(r) = 0 Initial condition: w(r,0) = 1- r^2 = us Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number N(int): number of equations wold(array): solution from previous iteration Returns: wnew(array): solution at time t^n+1 """ wold = wold[1:] # in this version of startup w0 is not solved with tdma N = N - 1 # this version has one less unknown to be solved with tdma tmp1 = D * (1. - theta) a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1, N): fac = 0.5 / (j + 1) a[j] = -D * theta * (1 - fac) b[j] = (1 + 2 * D * theta) c[j] = -D * theta * (1 + fac) d[j] = tmp1 * ((1 - fac) * wold[j - 1] + (1 + fac) * wold[j + 1]) + (1 - 2 * tmp1) * wold[j] b[0] = 1 + 4 * D * theta / 3 c[0] = -4 * D * theta / 3 d[0] = (1 - 4 * tmp1 / 3.) * wold[0] + 4 * tmp1 * wold[1] / 3. wnew = tdma(a, b, c, d) # solve with tdma w0 = (4 * wnew[0] - wnew[1]) / 3 wnew = np.append(np.append(w0, wnew), [0]) # add BCs return wnew
def solveNextTimestepStartupV2(theta, D, N, wold): """ Method that sets up the tridiagonal theta-scheme for the startup of flow in a pipe (Szymanski's problem). The method solves only for the next time-step, using standard tdma solver. The Governing equation is: dw/dt = w'' + w'/r, w = w(r,t), 0 < r < 1 where w' denotes dw/dr. velocity field: u(r,t) = us(r) -w(r,t) where us = 1 - r^2 Boundary conditions: w(0) = (4w(1)-w(2))/3), w(r) = 0 Initial condition: w(r,0) = 1- r^2 = us Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number N(int): number of equations wold(array): solution from previous iteration Returns: wnew(array): solution at time t^n+1 """ wold = wold[1:] # in this version of startup w0 is not solved with tdma N = N - 1 # this version has one less unknown to be solved with tdma tmp1 = D*(1. - theta) a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1,N): fac = 0.5 / (j + 1) a[j] = -D*theta*(1 - fac) b[j] = (1 + 2*D*theta) c[j] = -D*theta*(1 + fac) d[j] = tmp1*((1 - fac)*wold[j - 1] + (1 + fac)*wold[j + 1]) + (1 - 2*tmp1)*wold[j] b[0] = 1 + 4*D*theta/3 c[0] = -4*D*theta/3 d[0] = (1-4*tmp1/3.)*wold[0] + 4*tmp1*wold[1]/3. wnew = tdma(a, b, c, d) # solve with tdma w0 = (4*wnew[0]-wnew[1])/3 wnew = np.append(np.append(w0, wnew), [0]) # add BCs return wnew
def solveNextTimestepCouette(theta, D, N, uold): """ Method that sets up the tridiagonal theta-scheme for the transient couettflow. At time t=t0 the plate starts moving at y=0 The method solves only for the next time-step, using standard tdma solver. The Governing equation is: du/dt = d^2(u)/dx^2 , u = u(y,t), 0 < y < 1 Boundary conditions: u(0, t) = 1, u(1, t) = 0 Initial condition: u(t, 0) = 0 t<0, u(t, 0) = 1 t>0 Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number N(int): number of equations uold(array): solution from previous iteration Returns: unew(array): solution at time t^n+1 """ u0 = uold[0] uold = uold[1:] N = N - 1 tmp1 = D * (1. - theta) a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1, N): a[j] = -D * theta b[j] = (1. + 2 * D * theta) c[j] = -D * theta d[j] = tmp1 * (uold[j - 1] + uold[j + 1]) + (1. - 2 * tmp1) * uold[j] b[0] = (1 + 2 * D * theta) c[0] = -D * theta d[0] = tmp1 * (u0 + uold[1]) + (1. - 2 * tmp1) * uold[0] + D * theta * u0 unew = tdma(a, b, c, d) # solve with tdma unew = np.append(np.append(1., unew), 0.) # add BCs return unew
def solveNextTimestepCouette(theta, D, N, uold): """ Method that sets up the tridiagonal theta-scheme for the transient couettflow. At time t=t0 the plate starts moving at y=0 The method solves only for the next time-step, using standard tdma solver. The Governing equation is: du/dt = d^2(u)/dx^2 , u = u(y,t), 0 < y < 1 Boundary conditions: u(0, t) = 1, u(1, t) = 0 Initial condition: u(t, 0) = 0 t<0, u(t, 0) = 1 t>0 Args: theta(float): parameter between 0 and 1 seperating different schemes (FTCS, Laasonen, Crank-Nicolson...) D(float): Numerical diffusion number N(int): number of equations uold(array): solution from previous iteration Returns: unew(array): solution at time t^n+1 """ u0 = uold[0] uold = uold[1:] N = N - 1 tmp1 = D*(1. - theta) a = np.zeros(N) b = np.zeros(N) c = np.zeros(N) d = np.zeros(N) for j in range(1,N): a[j] = -D*theta b[j] = (1. + 2*D*theta) c[j] = -D*theta d[j] = tmp1*(uold[j - 1] + uold[j + 1]) + (1. - 2*tmp1)*uold[j] b[0] = (1 + 2*D*theta) c[0] = -D*theta d[0] = tmp1*(u0 + uold[1]) + (1. - 2*tmp1)*uold[0] + D*theta*u0 unew = tdma(a, b, c, d) # solve with tdma unew = np.append(np.append(1., unew), 0.) # add BCs return unew
it, itmax, dymax, RelTol = 0, 15, 1., 10**-10 legends=[] while (dymax > RelTol) and (it < itmax): """iteration process of linearized system of equations using taylor """ plot(x,ym) # plot ym for iteration No. it legends.append(str(it)) it = it + 1 a = np.ones(n) c = np.ones(n) b = -(np.ones(n)*2. + fac*ym) d = -(fac*0.5*ym**2) d[n-1] = d[n-1]-1 d[0] = d[0]-4 ym1 = tdma(a,b,c,d) # solution dymax = np.max(np.abs((ym1-ym)/ym)) ym = ym1 print('it = {}, dymax = {} '.format(it, dymax)) legend(legends,loc='best',frameon=False) ya = 4./(1+x)**2 feil = np.abs((ym1-ya)/ya) print "\n" for l in range(len(x)): print 'x = {}, y = {}, ya = {}'.format(x[l], ym1[l], ya[l])
1 - x ) # initial guess of y. ym = np.zeros(n) will converge to y1. ym = -20*x*(1-x) for instance will converge to y2 itmax = 15 for it in range(itmax): """iteration process of linearized system of equations""" # need to set a, b, c and d vector inside for loop since indices are changed in tdma solver a = np.ones(n) c = np.ones(n) b = -(np.ones(n) * 2. + fac * ym) d = -(np.ones(n) * fac * 0.5 * ym**2) d[n - 1] = -1. d[0] = -4. ym1 = tdma(a, b, c, d) # solution dy = np.abs(ym1 - ym) tr2 = np.max(dy) / np.max(np.abs(ym1)) tr3 = np.sum(dy) / np.sum(np.abs(ym1)) ym = ym1 print 'it = {}, tr2 = {}, tr3 = {} '.format(it, tr2, tr3) ya = 4. / (1 + x)**2 feil = np.abs((ym1 - ya) / ya) # plotting: legends = [] # empty list to append legends as plots are generated # Add the labels plot(x, ym1, "b") # plot numerical solution legends.append('y2 numerical')