def get_oblique_shock_grid(delta, I): # Grid as per ASM2010 AIAA code verification paper # Ramp at I/2 J = int(I / 2) x_min = -1 x_corner = 0 y = (x_corner - x_min) x_end_dist = (x_corner - x_min) # eta_min start_point = Point(x_min, 0) corner_point = Point(x_corner, 0) end_point = Point(x_end_dist * np.cos(delta), x_end_dist * np.sin(delta)) r1 = BoundaryGrids.fit_line(start_point, corner_point, int(I / 2)) r2 = BoundaryGrids.fit_line(corner_point, end_point, int(I / 2)) r = np.append(r1[:-1], r2) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(r) I = len(bd1.Points) - 1 # eta_max start_point = Point(x_min, y) corner_point = Point(x_corner, y) # end_point = Point(x_end_dist*np.cos(delta), x_end_dist*np.sin(delta) + y) end_point = Point(x_end_dist * np.cos(delta), y) # r1 = BoundaryGrids.fit_line(start_point, corner_point, int(I/2)) # r2 = BoundaryGrids.fit_line(corner_point, end_point, int(I/2)) # r = np.append(r1[:-1], r2) r = BoundaryGrids.fit_line(start_point, end_point, I) bd2 = Boundary(I, BdType.eta_max) bd2.populate_boundary_ndar_points(r) # xi_min start_point = Point(x_min, 0) end_point = Point(x_min, y) r = BoundaryGrids.fit_line(start_point, end_point, J) bd3 = Boundary(J, BdType.xi_min) bd3.populate_boundary_ndar_points(r) # xi_max start_point = Point(x_end_dist * np.cos(delta), x_end_dist * np.sin(delta)) end_point = Point(x_end_dist * np.cos(delta), y) r = BoundaryGrids.fit_line(start_point, end_point, J) bd4 = Boundary(J, BdType.xi_max) bd4.populate_boundary_ndar_points(r) Grid_obj = StructuredGridGeneration.get_univariate_grid(bd1, bd2, bd3, bd4) Grid_obj.save_to_vtk('oblique_shock.vtk') Grid_obj.save_to_txt('oblique_shock.txt')
def get_trap_grid(I, J): # Grid as per ASM2010 AIAA code verification paper # eta_min start_point = Point(0., 0.) end_point = Point(0.3, 0.0) r = BoundaryGrids.fit_line(start_point, end_point, I) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(r) # eta_max start_point = Point(0., 0.1) end_point = Point(0.3, 0.005) r = BoundaryGrids.fit_line(start_point, end_point, I) bd2 = Boundary(I, BdType.eta_max) bd2.populate_boundary_ndar_points(r) # xi_min start_point = Point(0., 0.) end_point = Point(0., 0.1) r = BoundaryGrids.fit_line(start_point, end_point, J) bd3 = Boundary(J, BdType.xi_min) bd3.populate_boundary_ndar_points(r) # xi_max start_point = Point(0.3, 0.) end_point = Point(0.3, 0.005) r = BoundaryGrids.fit_line(start_point, end_point, J) bd4 = Boundary(J, BdType.xi_max) bd4.populate_boundary_ndar_points(r) Grid_obj = StructuredGridGeneration.get_univariate_grid(bd1, bd2, bd3, bd4) Grid_obj.save_to_vtk('trap.vtk') Grid_obj.save_to_txt('trap.txt')
def get_circle_boundary(radius, centre, bd_eta_max): # centre is an object of point data type I = bd_eta_max.n r = np.empty(I+1, dtype=object) # Find point on circles such that line from circle # to eta_max boundary is normal to circle # theta = arctan((y - yc) / (x - xc)) points = bd_eta_max.Points for xi in range(I+1): point = points[xi] xp, yp = point.x, point.y dist = np.sqrt((xp - centre.x)**2 + (yp - centre.y)**2) costheta = (xp - centre.x) / dist sintheta = (yp - centre.y) / dist x = centre.x + radius*costheta y = centre.y + radius*sintheta r[xi] = Point(x, y) # x = np.empty(I+1) # y = np.empty(I+1) # for i in range(I+1): # x[i] = r[i].x # y[i] = r[i].y # plt.plot(x, y, 'k.') # plt.show() bd = Boundary(I, BdType.eta_min) bd.populate_boundary_ndar_points(r) return bd
def get_shock_BL_grid(delta, I): # Grid as per ASM2010 AIAA code verification paper # Ramp at I/2 J = int(I / 2) x_min = 0 x_corner = 0.1 x_mid = 0.2 * x_corner y = 0.0368 x_end_dist = x_corner - x_min # eta_max start_point = Point(x_min, y) turning_point = Point(x_mid, (x_mid - x_min) * np.tan(delta) + y) end_point = Point(x_corner, -(x_corner-x_mid)*np.tan(delta) + \ turning_point.y) r1 = BoundaryGrids.fit_line(start_point, turning_point, int(I * 0.2)) r2 = BoundaryGrids.fit_line(turning_point, end_point, int(I * 0.8)) r = np.append(r1[:-1], r2) bd2 = Boundary(I, BdType.eta_max) bd2.populate_boundary_ndar_points(r) I = len(bd2.Points) - 1 # eta_min start_point = Point(x_min, 0.) end_point = Point(x_corner, .0) r = BoundaryGrids.fit_line(start_point, end_point, I) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(r) dt = 3.0 # xi_min start_point = Point(x_min, 0) end_point = Point(x_min, y) stretching_f = lambda xi: 1 + (np.tanh(dt * (xi - 1)) / np.tanh(dt)) r = BoundaryGrids.fit_line(start_point, end_point, J, stretching_f) bd3 = Boundary(J, BdType.xi_min) bd3.populate_boundary_ndar_points(r) # xi_max start_point = Point(x_corner, 0.) end_point = Point(x_corner, -(x_corner-x_mid)*np.tan(delta) + \ turning_point.y) r = BoundaryGrids.fit_line(start_point, end_point, J, stretching_f) bd4 = Boundary(J, BdType.xi_max) bd4.populate_boundary_ndar_points(r) Grid_obj = StructuredGridGeneration.get_univariate_grid( bd1, bd2, bd3, bd4, stretching_f) Grid_obj.save_to_vtk('shock_BL.vtk') Grid_obj.save_to_txt('shock_BL.txt')
def get_airfoil_dat_gridgen(): xt, yt = zip(*np.loadtxt('top')) xb, yb = zip(*np.loadtxt('bottom')) CPt = [] CPb = [] for i in range(len(xt)): CPt.append(Point(xt[i], yt[i])) for i in range(len(xb)): CPb.append(Point(xb[i], yb[i])) I = 200 # xi_spacing_f = lambda xi, I: 0.5 * I * (1 - np.cos(xi * np.pi / I)) xi_spacing_f = lambda xi, I: xi s_CP_f = lambda j, n, I: j * I / n s_CP_inverse_f = lambda s, n, I: s * n / I rt = fit_cubic_spline(CPt, I, xi_spacing_f, s_CP_f, s_CP_inverse_f) rb = fit_cubic_spline(CPb, I, xi_spacing_f, s_CP_f, s_CP_inverse_f) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(rt) bd2 = Boundary(I, BdType.eta_min) bd2.populate_boundary_ndar_points(rb) xtnew = [] ytnew = [] xbnew = [] ybnew = [] for i in range(len(rt)): xtnew.append(rt[i].x) ytnew.append(rt[i].y) for i in range(len(rb)): xbnew.append(rb[i].x) ybnew.append(rb[i].y) np.savetxt('top-new', zip(xtnew, ytnew)) np.savetxt('bottom-new', zip(xbnew, ybnew)) plt.plot(xtnew, ytnew, '*-') plt.plot(xbnew, ybnew, '.-') plt.axis('equal') plt.show()
def fit_semicircle(Radius, t1, t2, centre, I, stretching_f=lambda xi: xi): # Assuming 2D. centre is a dictionary with 'x' and 'y' as keys # t1 and t2 - theta ranges - in radians r = np.empty(I + 1, dtype=object) for xi in range(I + 1): s = stretching_f(xi) t = (s * (t2 - t1) / I) + t1 x = centre['x'] + Radius * np.cos(t) y = centre['y'] + Radius * np.sin(t) r[xi] = Point(x, y) return r
def fit_line_old(start, end, I, stretching_f=lambda xi: xi): # I + 1 is the number of grid points # start and stop are 2 dictionaries have x and y as keys r = np.empty(I + 1, dtype=object) for xi in range(I + 1): s = stretching_f(xi / I) print start['x'] print xi x = ((1 - s) * start['x']) + (s * end['x']) y = ((1 - s) * start['y']) + (s * end['y']) r[xi] = Point(x, y) return r
def get_exp_plane_grid(I, J): delta = -10 * np.pi / 180 x_min = -1 x_corner = 0 y_max = (x_corner - x_min) * 1.5 x_end_dist = (x_corner - x_min) * 2 x_max = x_end_dist * np.cos(delta) y_min = x_end_dist * np.sin(delta) x_min = 0 x_max = 1 y_min = 0 y_max = 0.2 start_point = Point(x_min, y_min) end_point = Point(x_max, y_min) r = BoundaryGrids.fit_line(start_point, end_point, int(I)) bd1 = Boundary(len(r) - 1, BdType.eta_min) bd1.populate_boundary_ndar_points(r) start_point = Point(x_min, y_max) end_point = Point(x_max, y_max) r = BoundaryGrids.fit_line(start_point, end_point, int(I)) bd2 = Boundary(len(r) - 1, BdType.eta_max) bd2.populate_boundary_ndar_points(r) start_point = Point(x_min, y_min) end_point = Point(x_min, y_max) r = BoundaryGrids.fit_line(start_point, end_point, int(J)) bd3 = Boundary(len(r) - 1, BdType.xi_min) bd3.populate_boundary_ndar_points(r) start_point = Point(x_max, y_min) end_point = Point(x_max, y_max) r = BoundaryGrids.fit_line(start_point, end_point, int(J)) bd4 = Boundary(len(r) - 1, BdType.xi_max) bd4.populate_boundary_ndar_points(r) Grid_obj = StructuredGridGeneration.get_univariate_grid(bd1, bd2, \ bd3, bd4) # Grid_obj.save_to_vtk('ExpFan-IB.vtk', 'ExpFan-IB') # Grid_obj.save_to_txt('ExpFan-IB.txt') # Grid_obj.save_to_vtk('RampChannel-IB.vtk', 'RampChannel-IB') Grid_obj.save_to_txt('Rchannel-IB-2.txt')
def extract_control_points(filename): f = open(filename, 'r') f.readline() # First line - name of airfoil n = int(float(f.readline().split()[0])) # n is the number of control points or airfoil coordinates given f.readline() # Blank line # Start reading coordinates p_list = [] for i in range(n): x, y = f.readline().split() x, y = float(x), float(y) p_list.append(Point(x, y)) return p_list
def get_naca_grid_gridgen(): # Use points from naca equation as control points so that the trailing # edge is sharp x, y = get_IB_naca_4_dig('0012', chord_len=1.0, num_points=66) CP = [] for i in range(len(x)): CP.append(Point(x[i], y[i])) ################ Generating around airfoil I = 100 # xi_spacing_f = lambda xi, I: 0.5 * I * (1 - np.cos(xi * np.pi / I)) xi_spacing_f = lambda xi, I: xi s_CP_f = lambda j, n, I: j * I / n s_CP_inverse_f = lambda s, n, I: s * n / I r = fit_cubic_spline(CP, I, xi_spacing_f, s_CP_f, s_CP_inverse_f) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(r) x = [] y = [] for i in range(len(r)): x.append(r[i].x) y.append(r[i].y) return (x, y)
def get_circle(radius, centre, I): r = np.empty(I + 1, dtype=object) for xi in range(I + 1): t = 2 * np.pi * (1 - xi / I) x = centre.x + radius * np.cos(t) y = centre.y + radius * np.sin(t) r[xi] = Point(x, y) start = [] end = [] normals = [] for i in range(len(r) - 1): start.append([r[i].x, r[i].y]) end.append([r[i + 1].x, r[i + 1].y]) # Given a line segment, find dx = x2 - x1 and dy = y2 - y1 # The normal vector to the line segment is given by (dy, -dx) # We also need to normalise it dx = r[i + 1].x - r[i].x dy = r[i + 1].y - r[i].y ds = np.sqrt(dx**2 + dy**2) dx = dx / ds dy = dy / ds normals.append([-dy, dx]) return (start, end, normals)
def get_boundary_grids(): # Eta_max boundary I = 300 radius = 0.001 p1 = Point(21*radius, 5*radius) p2 = Point(-6*radius, 5*radius) p3 = Point(-6*radius, -5*radius) p4 = Point(21*radius, -5*radius) bd_eta_max, i_list = get_eta_max_boundary(p1, p2, p3, p4, I) I = bd_eta_max.n # Eta_min boundary centre = Point(0, 0) bd_eta_min = get_circle_boundary(radius, centre, bd_eta_max) # Xi min and max boundaries I = 200 start = Point(centre.x + radius, centre.y) end = 0.5 * (p1 + p4) bd_xi_min, bd_xi_max = get_xi_boundaries(start, end, I) print 'Index list: ', i_list return (bd_xi_min, bd_xi_max, bd_eta_min, bd_eta_max, i_list)
def get_ramp_grid(I, J): # Grid as per ASM2010 AIAA code verification paper # Ramp at I/3 x_bl = 0. y_bl = 0. x_rs = 0.25 y_rs = 0.0 x_re = 0.5 y_re = 0.067 x_br = 1.0 y_br = 0.067 x_tl = 0.0 y_tl = 0.2 x_tr = 1.0 y_tr = 0.2 # eta_min start_point = Point(x_bl, y_bl) end_point = Point(x_rs, y_rs) r1 = BoundaryGrids.fit_line(start_point, end_point, int(I / 4)) start_point = Point(x_rs, y_rs) end_point = Point(x_re, y_re) r2 = BoundaryGrids.fit_line(start_point, end_point, int(I / 4)) start_point = Point(x_re, y_re) end_point = Point(x_br, y_br) r3 = BoundaryGrids.fit_line(start_point, end_point, int(I / 2)) r = np.append(r1[:-1], r2) r = np.append(r[:-1], r3) bd1 = Boundary(I, BdType.eta_min) bd1.populate_boundary_ndar_points(r) I = len(bd1.Points) - 1 # eta_max start_point = Point(x_tl, y_tl) end_point = Point(x_tr, y_tr) r = BoundaryGrids.fit_line(start_point, end_point, I) bd2 = Boundary(I, BdType.eta_max) bd2.populate_boundary_ndar_points(r) # xi_min start_point = Point(x_bl, y_bl) end_point = Point(x_tl, y_tl) r = BoundaryGrids.fit_line(start_point, end_point, J) bd3 = Boundary(J, BdType.xi_min) bd3.populate_boundary_ndar_points(r) # xi_max start_point = Point(x_br, y_br) end_point = Point(x_tr, y_tr) r = BoundaryGrids.fit_line(start_point, end_point, J) bd4 = Boundary(J, BdType.xi_max) bd4.populate_boundary_ndar_points(r) print len(bd1.Points), len(bd2.Points), len(bd3.Points), len(bd4.Points) Grid_obj = StructuredGridGeneration.get_univariate_grid(bd1, bd2, bd3, bd4) Grid_obj.save_to_vtk('ramp_channel_uniform.vtk') Grid_obj.save_to_txt('ramp_channel_uniform.txt')
def get_plane_IB(delta, I, J): global plt x_min = -1.0 x_max = 5.0 y_min = -5.0 y_max = 5.0 airfoil_start = x_min + 43.5 / 100 * (x_max - x_min) airfoil_end = x_min + 57.5 / 100 * (x_max - x_min) airfoil_y_s = y_min + 48 / 100 * (y_max - y_min) airfoil_y_e = y_min + 52 / 100 * (y_max - y_min) dx = 0.01 dy = 0.01 # x_min = -6.0 * 0.01 # x_max = 21.0 * 0.01 # y_min = -5.0 * 0.01 # y_max = 5.0 * 0.01 # airfoil_start = x_min + 15.38/100*(x_max - x_min) # airfoil_end = x_min + 26.92/100*(x_max - x_min) # airfoil_start = -1 * 0.01 # airfoil_end = 1 * 0.01 # airfoil_y_s = y_min + 40./100*(y_max - y_min) # airfoil_y_e = y_min + 60./100*(y_max - y_min) # airfoil_y_s = -2.5 * 0.01 # airfoil_y_e = 2.5 * 0.01 # dx = 0.02 * 0.01 # dy = 0.02 * 0.01 length1 = abs(airfoil_start - y_min) length2 = abs(x_max - airfoil_end) delta1 = BoundaryGrids.find_hyp_tan_stretching_factor( dx, int(I / 4), length1) delta2 = BoundaryGrids.find_hyp_tan_stretching_factor( dx, int(3 * I / 4), length2) stretching_f1 = lambda xi: 1 + (np.tanh(delta1 * (xi - 1)) / np.tanh(delta1)) stretching_f2 = lambda xi: 1 + (np.tanh(delta2 * (xi - 1)) / np.tanh(delta2)) end_point = Point(x_min, y_min) start_point = Point(airfoil_start, y_min) r1_t = BoundaryGrids.fit_line(start_point, end_point, int(I / 4), stretching_f1) r1 = np.empty(len(r1_t), dtype=object) for i in range(len(r1)): r1[i] = r1_t[len(r1) - 1 - i] num = int((airfoil_end - airfoil_start) / dx) + 1 start_point = Point(airfoil_start, y_min) end_point = Point(airfoil_end, y_min) r2 = BoundaryGrids.fit_line(start_point, end_point, num) start_point = Point(airfoil_end, y_min) end_point = Point(x_max, y_min) r3 = BoundaryGrids.fit_line(start_point, end_point, int(3 * I / 4), stretching_f2) r = np.append(r1[:-1], r2) r = np.append(r[:-1], r3) bd1 = Boundary(len(r) - 1, BdType.eta_min) bd1.populate_boundary_ndar_points(r) f = plt.figure() plt = bd1.plot_boundary(plt, 'eta_min') end_point = Point(x_min, y_max) start_point = Point(airfoil_start, y_max) r1_t = BoundaryGrids.fit_line(start_point, end_point, int(I / 4), stretching_f1) r1 = np.empty(len(r1_t), dtype=object) for i in range(len(r1)): r1[i] = r1_t[len(r1) - 1 - i] num = int((airfoil_end - airfoil_start) / dx) + 1 start_point = Point(airfoil_start, y_max) end_point = Point(airfoil_end, y_max) r2 = BoundaryGrids.fit_line(start_point, end_point, num) start_point = Point(airfoil_end, y_max) end_point = Point(x_max, y_max) r3 = BoundaryGrids.fit_line(start_point, end_point, int(3 * I / 4), stretching_f2) r = np.append(r1[:-1], r2) r = np.append(r[:-1], r3) bd2 = Boundary(len(r) - 1, BdType.eta_max) bd2.populate_boundary_ndar_points(r) plt = bd2.plot_boundary(plt, 'eta_max') I = len(r) - 1 # start_point = Point(x_min, y_min) # end_point = Point(x_min, y_max) # A = 3 # L = 1 # yc = 0.5 # stretching_f = lambda xi: (L*xi) + A*(yc - L*xi)*(1 - xi)*xi # r = BoundaryGrids.fit_line(start_point, end_point, int(J), stretching_f) # bd3 = Boundary(len(r)-1, BdType.xi_min) # bd3.populate_boundary_ndar_points(r) # plt = bd3.plot_boundary(plt, 'xi_min') # start_point = Point(x_max, y_min) # end_point = Point(x_max, y_max) # A = 3 # L = 1 # yc = 0.5 # stretching_f = lambda xi: (L*xi) + A*(yc - L*xi)*(1 - xi)*xi # r = BoundaryGrids.fit_line(start_point, end_point, int(J), stretching_f) # bd4 = Boundary(len(r)-1, BdType.xi_max) # bd4.populate_boundary_ndar_points(r) # plt = bd4.plot_boundary(plt, 'xi_max') # plt.show() num = int((airfoil_y_e - airfoil_y_s) / dy) + 1 K = int(J / 2) + int(J / 2) + num Grid_obj = TwoDGrid(I + 1, K + 1) Grid_obj.set_boundary(bd1) Grid_obj.set_boundary(bd2) Grid = Grid_obj.Grid length1 = abs(airfoil_y_s - y_min) length2 = abs(y_max - airfoil_y_e) delta1 = BoundaryGrids.find_hyp_tan_stretching_factor( dy, int(J / 2), length1) delta2 = BoundaryGrids.find_hyp_tan_stretching_factor( dy, int(J / 2), length2) stretching_f1 = lambda xi: 1 + (np.tanh(delta1 * (xi - 1)) / np.tanh(delta1)) stretching_f2 = lambda xi: 1 + (np.tanh(delta2 * (xi - 1)) / np.tanh(delta2)) for xi in range(0, I + 1): P_eta_min = Grid[xi, 0] P_eta_max = Grid[xi, K] end_point = P_eta_min start_point = Point(P_eta_min.x, airfoil_y_s) r1_t = BoundaryGrids.fit_line(start_point, end_point, int(J / 2), stretching_f1) r1 = np.empty(len(r1_t), dtype=object) for i in range(len(r1)): r1[i] = r1_t[len(r1) - 1 - i] # num = int((airfoil_y_e - airfoil_y_s)/ 0.005) + 1 start_point = Point(P_eta_min.x, airfoil_y_s) end_point = Point(P_eta_max.x, airfoil_y_e) r2 = BoundaryGrids.fit_line(start_point, end_point, num) start_point = Point(P_eta_max.x, airfoil_y_e) end_point = P_eta_max r3 = BoundaryGrids.fit_line(start_point, end_point, int(J / 2), stretching_f2) r = np.append(r1[:-1], r2) r = np.append(r[:-1], r3) # K = int(J/2) + int(J/2) + num # print len(r1), len(r2), len(r3), len(r), J, K Grid[xi, :] = r # Grid_obj = StructuredGridGeneration.get_univariate_grid(bd1, bd2, \ # bd3, bd4, stretching_f) Grid_obj.save_to_vtk('Circle-IB.vtk', 'Circle-IB') Grid_obj.save_to_txt('Circle-IB.txt')
def fit_cubic_spline(CP, I, xi_spacing_f=lambda xi: xi, s_CP_f=lambda j,n,I: \ j*I/n, s_CP_inverse_f=lambda s,n,I: s*n/I): # CP is the list of control points # It should be a list of dictionaries with keys 'x' and 'y' # I + 1 is the number of grid points # Note: xi ranges from 0 to I and is an integer only # xi_spacing_f is a function handle that transforms the spacing between # consecutive xi. This should return values in the same range as that of xi. # The default argument is equal spacing. # Note that now, s = xi_spacing(xi). Hence the grid generation parameter # is 's' and not xi. However since xi is an integer only, it can be used # as array index. # s_CP_f is a function handle which gives the value of s given the index of # control point j, i.e., it return s_j. The values of s at the intermediate # control points s_j can be got from equal spacing between s_0 and s_I. # s_CP_inverse_f is the function that returns the value of 'j' given a value # s. The s_CP_f function can be though of a map between the 'j' space and # the 's' space (0<=j<=n and 0<=s<=I). This function is the reverse map. # Non integer values of 'j' dont have any physical meaning. But the floor # and ceil of j correspond to s_j and s_j+1 which give the location of the # j and j+1 th control point respectively. This can be used to give the # equation of the jth cubic spline that was generated n = len(CP) # Solving for second derivative of r, implicitly r_dd_CP_x = np.zeros((n)) r_dd_CP_y = np.zeros((n)) r_dd_CP_x[0] = 0 r_dd_CP_x[n - 1] = 0 r_dd_CP_y[0] = 0 r_dd_CP_y[n - 1] = 0 # M is the same for x or y coordinate M = np.zeros((n - 2, n - 2)) # No need to solve for first and last r_dd b_x = np.zeros((n - 2)) # RHS of the implicit equation b_y = np.zeros((n - 2)) # RHS of the implicit equation delta = lambda j: s_CP_f(j + 1, n - 1, I) - s_CP_f(j, n - 1, I) for j in range(n - 2): # The delta function is written taking into account that the value of j # ranges from 0 to n-1. The inner points hence take value of j such that # 1 <= j <= n-2. But the computational domain is from 0 <= j <= n-3 # (array index). # Hence all delta function calls should be made with j -> j+1 # Also, all calls to CP should also be made with j -> j+1 if j > 0: M[j, j - 1] = delta(j - 1 + 1) / 6.0 # c_i M[j, j] = (delta(j - 1 + 1) + delta(j + 1)) / 3.0 # d_i if j < n - 3: M[j, j + 1] = delta(j + 1) / 6.0 # a_i b_x[j] = (-1 * (CP[j + 1].x - CP[j-1 + 1].x) / delta(j-1 + 1)) + \ (+1 * (CP[j+1 + 1].x - CP[j + 1].x) / delta(j + 1)) b_y[j] = (-1 * (CP[j + 1].y - CP[j-1 + 1].y) / delta(j-1 + 1)) + \ (+1 * (CP[j+1 + 1].y - CP[j + 1].y) / delta(j + 1)) # Now use TDMA solver r_dd_CP_x[1:n - 1] = Thomas_algorithm(M, b_x) r_dd_CP_y[1:n - 1] = Thomas_algorithm(M, b_y) r_dd_CP = np.empty(n, dtype=object) for i in range(n): r_dd_CP[i] = Point(r_dd_CP_x[i], r_dd_CP_y[i]) # Now we can construct the cubic spline # Note, we will construct the cubic spline at integer values of xi. # The equivalent 's' is found as xi_spacing_f(xi). # The values of s at the control points are found using the function # s_CP_f. # Cubic polynomials have been constructed between the control points # But, given a value of s, it is necessary to know which interval that s # belongs to, i.e., which 'j' # That shall be the inverse of the function s_CP_f which is s_CP_inverse_f. # But the inverse will return a fractional value. Hence, the floor and ceil # of that number will give the required interval r = np.empty(I + 1, dtype=object) r[0] = Point(CP[0].x, CP[0].y) r[I] = Point(CP[n - 1].x, CP[n - 1].y) for xi in range(1, I): s = xi_spacing_f(xi, I) j = s_CP_inverse_f(s, n - 1, I) if int(round(j * 10)) % 10 == 0: j_l = int(j) if j_l == n: j_l = n - 1 j_u = j_l + 1 else: j_l = int(np.floor(j)) j_u = int(np.ceil(j)) s_l = s_CP_f(j_l, n - 1, I) s_u = s_CP_f(j_u, n - 1, I) # xi is used as the array index since it is always an integer r[xi] = (s_u - s)**3 * r_dd_CP[j_l] / (6.0 * (s_u - s_l)) + \ (s - s_l)**3 * r_dd_CP[j_u] / (6.0 * (s_u - s_l)) + \ ( (s_u - s) * \ ((CP[j_l] / (s_u - s_l)) - ((s_u - s_l) * \ r_dd_CP[j_l]/6.0)) ) + \ ( (s - s_l) * \ ((CP[j_u] / (s_u - s_l)) - ((s_u - s_l) * \ r_dd_CP[j_u]/6.0)) ) return r
def read_from_file(filename): start = [] end = [] normals = [] f = open(filename, 'r') # First line contains number of iblines num_iblines = int(f.readline()) for i in range(num_iblines): line = f.readline() data = line.split() data = [float(d) for d in data] start.append([data[0], data[1]]) end.append([data[2], data[3]]) normals.append([data[4], data[5]]) return (start, end, normals) if __name__ == '__main__': # x, y = get_naca_grid_gridgen() # start, end, normals = get_lines_from_upper_airfoil(x, y) radius = 0.005 centre = Point(0., 0.) I = 50 # start, end, normals = get_circle(radius, centre, I) # start, end, normals = get_exp_fan_IB() start, end, normals = get_concave_polygon() plot_start_end_normals(start, end, normals) filename = 'concave.dat' put_to_file(start, end, normals, filename)