├── CDMatrix.py ├── README.txt ├── matrixPlotter.py └── CFDSolver.py /CDMatrix.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | AUTHOR: Thomas Kosciuch 2 | DATE: Nov 30th 2019 3 | PURPOSE: Solve CFD problems using Central Difference, Upwind Difference, and SIMPLE 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /matrixPlotter.py: -------------------------------------------------------------------------------- 1 | import matplotlib # enables graphing 2 | import matplotlib.cm as cm 3 | import matplotlib.mlab as mlab 4 | import matplotlib.pyplot as plt 5 | import buildMatrix as matrix 6 | import numpy as np 7 | 8 | def Contour(Ans, B , x_length=1, y_length=1,name="figure", titleTxt="",debug='n'): 9 | x_nodes = len(Ans[1][:]) 10 | y_nodes = len(Ans[:][1]) 11 | dx = float(x_length) / x_nodes 12 | dy = float(y_length) / y_nodes 13 | xpos = [0] * x_nodes # calculating position along x 14 | ypos = [0] * y_nodes # calculating position along y 15 | xpos[0] = dx / 2 # populating the first x-node 16 | ypos[0] = dy / 2 # populating the first y-node 17 | for i in range(x_nodes-1): 18 | xpos[i+1] = xpos[i] + dx 19 | for i in range(y_nodes-1): 20 | ypos[i+1] = ypos[i] + dy 21 | # plotting line 22 | x_line = [0] * x_nodes 23 | y_line = [0] * x_nodes 24 | for i in range(x_nodes): 25 | x_line[i] = xpos[i] 26 | y_line[i] = y_length-ypos[i] 27 | 28 | if debug == "y": 29 | print("building mesh") 30 | X, Y = np.meshgrid(xpos, ypos) 31 | # PLOTTING CONTOUR PLOTS 32 | # note: these will save in a directory called "plot" 33 | plt.figure() 34 | # Graphing gradient function with a bilinear interpolation 35 | im = plt.imshow(Ans, interpolation='bilinear', origin='lower', 36 | extent=(0, 1, 0, 1)) # plottin interpolation 37 | CBI = plt.colorbar(im, shrink=0.9) # creating colour-bar 38 | plt.axis([0, x_length, 0, y_length]) # plotting boundaries 39 | CS = plt.contour(X, Y, Ans, colors='k') # plotting contours 40 | plt.clabel(CS, fontsize=9, colors='k') # populating lable 41 | plt.plot(x_line,y_line) # plotting the transcects 42 | plt.title(titleTxt) 43 | plt.savefig("plots/"+name+"Ans.png", bbox_inches='tight') 44 | plt.gcf().clear() 45 | print("figure saved") 46 | 47 | def Error(Ans, x_length = 1, name="figure"): 48 | x_nodes = len(Ans[1][:]) 49 | dx = x_length / x_nodes 50 | xpos = [0] * x_nodes # calculating position along x 51 | y_nodes = len(Ans[:][1]) 52 | a_line = [0] * x_nodes 53 | x_line = [0] * x_nodes 54 | for i in range(x_nodes-1): 55 | xpos[i+1] = xpos[i] + dx 56 | for i in range(x_nodes): 57 | a_line[i] = Ans[y_nodes-i-1][i] 58 | x_line[i] = xpos[i] 59 | plt.figure() 60 | yaxisMax = (max(max(Ans)) + max(max(Ans))*0.05) 61 | plt.axis([0, x_length, 0, yaxisMax]) 62 | titleTxt = "" 63 | ylabText = "Temperature (" + '\u00b0 C' + ")" 64 | plt.ylabel = ylabText 65 | plt.plot(x_line,a_line) 66 | plt.title(titleTxt) 67 | plt.savefig("plots/"+name+"Err.png" , bbox_inches='tight') 68 | 69 | 70 | -------------------------------------------------------------------------------- /CFDSolver.py: -------------------------------------------------------------------------------- 1 | ############## 2 | # title: Using Upwind and Central Difference to solve linear and vortex flow 3 | # by: thomas kosciuch 4 | # email: thomas.kosciuch@mail.utoronto.ca 5 | # 6 | # note, plots save in a 'plot' directory, 7 | # and text files save in a 'txt' directory 8 | # 9 | # SOURCES: 10 | # Math: https://github.com/mitya57/python-markdown-math 11 | # Scipy: https://github.com/scipy/scipy 12 | # Time: https://github.com/time 13 | # Sys: https://github.com/sys 14 | # tqdm: https://github.com/tqdm/ 15 | # numpy: https://github.com/numpy/numpy 16 | # future: https://github.com/python/cpython/blob/2.7/Lib/__future__.py 17 | # matplotlib: https://github.com/matplotlib/matplotlib 18 | # 19 | # __ I M P O R T I N G # 20 | from __future__ import division # solution to complete division using floats 21 | import numpy as np # 22 | import numpy.linalg # direct solver for solution 23 | import math # 24 | import scipy.sparse.linalg # incase we want our nodes to be > 160 25 | 26 | import time # enables timing for debugging purposes 27 | import sys # allows integer inputs 28 | from tqdm import tqdm # enables asking questions 29 | import matrixPlotter as Plotter 30 | import buildMatrix as matrix 31 | # __ K N O W N S _ # 32 | # note node numbers, u's and gammas all subject to change 33 | x_length = 1 # length of X, float 34 | y_length = 1 # length of Y, float 35 | x_nodes = 40 # number of nodes, integer 36 | y_nodes = 40 # number of nodes, integer 37 | Circ = 'y' 38 | Scheme = 'u' 39 | debug = 'n' 40 | x_u = 0.1 # 41 | x_v = 0.1 # 42 | Gamma = 0.1 # diffusion coefficient 43 | phi_N = 100 # boundary at N 44 | phi_E = 0 # boundary at E 45 | phi_S = 0 # boundary at N 46 | phi_W = 100 # boundary at E 47 | density = 1 # rho term 48 | Boundary = [phi_W, phi_E, phi_S, phi_N] 49 | 50 | # SIMPLE MATH 51 | dim = y_nodes * x_nodes # dimension of a-matrix 52 | dx = x_length / x_nodes # node size for static grid along x 53 | dy = y_length / y_nodes # node size for static gris along y 54 | x_pos, y_pos = matrix.meshposition(x_nodes,y_nodes,dx,dy) 55 | 56 | # C A L C U L A T I N G V E L O C I T Y # 57 | 58 | x_u = [x_u] * dim # u(x) values are populated 59 | x_v = [x_v] * dim # u(y) values 60 | # vortex will over-ride: 61 | if Circ == "y": 62 | print("calculating circular velocities") 63 | matrix.CircV(x_pos,y_pos,x_length,y_length, dim) 64 | 65 | # C A L C U L A T I N G P E C L E T No. # 66 | F_x = [0] * dim 67 | F_y = [0] * dim 68 | D_x = Gamma / dx 69 | D_y = Gamma / dy # This allows the calculation of a 1-D system 70 | 71 | if x_nodes == 1: # along x- and y- 72 | D_x = 0 # which is very helpful for checking programming 73 | if y_nodes == 1: 74 | D_y = 0 75 | 76 | for i in range(dim): 77 | F_x[i] = density * x_u[i] # calculates F-values along x 78 | F_y[i] = density * x_v[i] # calculates F-values along y 79 | 80 | # Central Difference 81 | if Scheme == "c": 82 | a, B = matrix.CDiff(x_nodes, y_nodes, D_x, D_y, F_x, F_y, Boundary, debug) 83 | print("central difference") 84 | 85 | # Upwind Difference 86 | if Scheme == "u": 87 | a, B = matrix.UDiff(x_nodes, y_nodes, D_x, D_y, F_x, F_y, Boundary, debug) 88 | print("upwind difference") 89 | 90 | 91 | xpos = [0] * x_nodes # calculating position along x 92 | ypos = [0] * y_nodes # calculating position along y 93 | xpos[0] = dx / 2 # populating the first x-node 94 | ypos[0] = dy / 2 # populating the first y-node 95 | 96 | for i in range(x_nodes-1): 97 | xpos[i+1] = xpos[i] + dx 98 | for i in range(y_nodes-1): 99 | ypos[i+1] = ypos[i] + dy 100 | 101 | if x_nodes < 170: # solution is direct if fewer than 170 nodes 102 | print("solving - direct") 103 | X = np.linalg.solve(a, B) 104 | print("direct - successful") 105 | else: # iterative solution for large matricies 106 | print("solving - Iterative") 107 | a_temp = np.asmatrix(a) 108 | x_temp = scipy.sparse.linalg.gmres(a_temp,B) 109 | if x_temp[1] is 0: 110 | print("interative - success") 111 | else: 112 | print("iterative - failure, I'm sorry - goodbye") 113 | quit 114 | X = x_temp[0] 115 | 116 | 117 | Ans = matrix.List2Matrix(X,x_nodes,y_nodes) 118 | print(Ans) 119 | 120 | # creating name for plotter 121 | name = "dif=" + str(Gamma) + " Sch=" + Scheme + " N=" + str(dim) + " u1:" + str(round(x_u[1],2)) 122 | 123 | # graphing plot and error plot 124 | Plotter.Contour(Ans, B, name=name) 125 | Plotter.Error(Ans, name=name) 126 | 127 | 128 | --------------------------------------------------------------------------------