diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-05-25 18:01:36 +0400 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-05-25 23:24:05 +0400 |
commit | 162641340305650b710c85f6ebace6f7a392ea1b (patch) | |
tree | b34dc214f25775a4a06091343ae916c84a4b5a68 | |
parent | cdb1ea09b5173576d795b99debc30219072a095d (diff) | |
download | CFD-SIMPLE-162641340305650b710c85f6ebace6f7a392ea1b.tar.gz |
feat: correct indices
-rw-r--r-- | src/main.py | 6 | ||||
-rw-r--r-- | src/plotter.py | 28 | ||||
-rw-r--r-- | src/research.py | 2 | ||||
-rw-r--r-- | src/simple.py | 193 |
4 files changed, 131 insertions, 98 deletions
diff --git a/src/main.py b/src/main.py index cdbf16e..27620b7 100644 --- a/src/main.py +++ b/src/main.py @@ -1,13 +1,13 @@ from simple import SIMPLE from research import Research -model = SIMPLE((1, 2), (0.7, 0.5), 0.02, 120) +model = SIMPLE((30, 30), (0, 0), 0.02, 40) -research = Research(model, '07x05_002') +research = Research(model, 'testing') is_complete = research.load() if is_complete: research.inspect() else: - research.solve(preview=True, save_plot=True, save_model=True) + research.solve(preview=True) diff --git a/src/plotter.py b/src/plotter.py index c803f3f..45d95da 100644 --- a/src/plotter.py +++ b/src/plotter.py @@ -1,5 +1,6 @@ import numpy as np import matplotlib.pyplot as plt +from copy import copy from matplotlib.patches import Rectangle figure, axes = plt.subplots() @@ -33,21 +34,32 @@ class Plotter: u = u / factor v = v / factor + + shape = (model.p.shape[0] + 1, model.p.shape[1] + 1) x, y = np.meshgrid( - np.linspace(0, model.domain_size[1], model.shape[1]), - np.linspace(0, model.domain_size[0], model.shape[0]), + np.linspace(0, shape[1] * model.step, shape[1]), + np.linspace(0, shape[0] * model.step, shape[0]), ) - density = density or int((max(model.domain_size) / model.step) / 40) + u = copy(model.u) + u.resize(shape) + v = copy(model.v) + v.resize(shape) + p = copy(model.p) + p.resize(shape) + + print(shape, u.shape, v.shape) + + # density = density or int((max(model.domain_size) / model.step) / 40) - plt.contourf(x, y, model.p) + plt.contourf(x, y, p) # self.patch = axes.add_patch(Rectangle((0, 0), *reversed(model.bfs_size), color='gray')) # TODO: allow using streamplot self.plt = plt.quiver( - x[::density, ::density], - y[::density, ::density], - u[::density, ::density], - v[::density, ::density], + x, + y, + u, + v, ) self.colorbar = plt.colorbar(label='Pressure') diff --git a/src/research.py b/src/research.py index d660f8e..2a59c49 100644 --- a/src/research.py +++ b/src/research.py @@ -34,7 +34,7 @@ class Research: if iteration % 10 == 0 or iteration == 1: if preview or save_plot: - self.plotter.plot(self.model) + self.plotter.plot(self.model, normalize=False, density=1) if preview: self.plotter.show() if save_plot: diff --git a/src/simple.py b/src/simple.py index 91ed1a4..b54cd38 100644 --- a/src/simple.py +++ b/src/simple.py @@ -2,34 +2,30 @@ import numpy as np class SIMPLE: - def __init__(self, domain_size, bfs_size, step, Re, alpha=0.8): + def __init__(self, shape, bfs_shape, step, Re, alpha=0.8): np.set_printoptions(precision=2, floatmode="maxprec", suppress=True) self.Re = Re self.nu = 1 / Re self.alpha = alpha - self.domain_size = domain_size - self.bfs_size = bfs_size - self.step = step - self.shape = tuple(int(x / step) for x in domain_size) - self.bfs_node_size = tuple(int(x / step) for x in bfs_size) + self.bfs_shape = bfs_shape # Allocations - self.u = self.allocate_field() - self.u_star = self.allocate_field() + self.u = np.zeros(shape=(shape[0], shape[1] + 1), dtype=float) + self.u_star = np.zeros(shape=(shape[0], shape[1] + 1), dtype=float) - self.v = self.allocate_field() - self.v_star = self.allocate_field() + self.v = np.zeros(shape=(shape[0] + 1, shape[1]), dtype=float) + self.v_star = np.zeros(shape=(shape[0] + 1, shape[1]), dtype=float) - self.p = self.allocate_field() - self.p_star = self.allocate_field(True) - self.p_prime = self.allocate_field() + self.p = np.zeros(shape=shape, dtype=float) + self.p_star = np.random.rand(*shape) + self.p_prime = np.zeros(shape=shape, dtype=float) - self.d_e = self.allocate_field() - self.d_n = self.allocate_field() - self.b = self.allocate_field() + self.d_e = np.zeros(shape=self.u.shape, dtype=float) + self.d_n = np.zeros(shape=self.v.shape, dtype=float) + self.b = np.zeros(shape=shape, dtype=float) def allocate_field(self, random=False): if random: @@ -47,7 +43,7 @@ class SIMPLE: def assert_positive(self, value): '''Assert that the value is nearly positive''' - assert value > -0.1, f'WARNING: Value must be positive: {value}' + assert value > -1, f'WARNING: Value must be positive: {value}' return value def grid(self): @@ -59,52 +55,56 @@ class SIMPLE: def solve_momentum_equations(self): # Momentum along X direction - for i, j in self.grid(): - u_E = 0.5 * (self.u[i][j] + self.u[i][j + 1]) - u_W = 0.5 * (self.u[i][j] + self.u[i][j - 1]) - v_N = 0.5 * (self.v[i - 1][j] + self.v[i - 1][j + 1]) - v_S = 0.5 * (self.v[i][j] + self.v[i][j + 1]) + for i in range(1, self.u.shape[0] - 1): + for j in range(1, self.u.shape[1] - 1): + u_W = 0.5 * (self.u[i][j] + self.u[i][j - 1]) + u_E = 0.5 * (self.u[i][j] + self.u[i][j + 1]) + + v_S = 0.5 * (self.v[i][j - 1] + self.v[i][j]) + v_N = 0.5 * (self.v[i + 1][j - 1] + self.v[i + 1][j]) - a_E = self.assert_positive(-0.5 * u_E * self.step + self.nu) - a_W = self.assert_positive(+0.5 * u_W * self.step + self.nu) - a_N = self.assert_positive(-0.5 * v_N * self.step + self.nu) - a_S = self.assert_positive(+0.5 * v_S * self.step + self.nu) + a_E = self.assert_positive(-0.5 * u_E * self.step + self.nu) + a_W = self.assert_positive(+0.5 * u_W * self.step + self.nu) + a_N = self.assert_positive(-0.5 * v_N * self.step + self.nu) + a_S = self.assert_positive(+0.5 * v_S * self.step + self.nu) - a_e = 0.5 * self.step * (u_E - u_W + v_N - v_S) + 4 * self.nu - A_e = -self.step + a_e = 0.5 * self.step * (u_E - u_W + v_N - v_S) + 4 * self.nu + A_e = -self.step - self.d_e[i][j] = A_e / a_e + self.d_e[i][j] = A_e / a_e - self.u_star[i][j] = ( - a_E * self.u[i][j + 1] + - a_W * self.u[i][j - 1] + - a_N * self.u[i - 1][j] + - a_S * self.u[i + 1][j] - ) / a_e + self.d_e[i][j] * (self.p_star[i][j + 1] - self.p_star[i][j]) + self.u_star[i][j] = ( + a_E * self.u[i][j + 1] + + a_W * self.u[i][j - 1] + + a_N * self.u[i + 1][j] + + a_S * self.u[i - 1][j] + ) / a_e + self.d_e[i][j] * (self.p_star[i][j - 1] - self.p_star[i][j]) # p - p_e # Momentum along Y direction - for i, j in self.grid(): - u_E = 0.5 * (self.u[i][j] + self.u[i + 1][j]) - u_W = 0.5 * (self.u[i][j - 1] + self.u[i + 1][j - 1]) - v_N = 0.5 * (self.v[i - 1][j] + self.v[i][j]) - v_S = 0.5 * (self.v[i][j] + self.v[i + 1][j]) + for i in range(1, self.v.shape[0] - 1): + for j in range(1, self.v.shape[1] - 1): + u_W = 0.5 * (self.u[i - 1][j] + self.u[i][j]) + u_E = 0.5 * (self.u[i - 1][j + 1] + self.u[i][j + 1]) + + v_N = 0.5 * (self.v[i][j] + self.v[i + 1][j]) + v_S = 0.5 * (self.v[i][j] + self.v[i - 1][j]) - a_E = self.assert_positive(-0.5 * u_E * self.step + self.nu) - a_W = self.assert_positive(+0.5 * u_W * self.step + self.nu) - a_N = self.assert_positive(-0.5 * v_N * self.step + self.nu) - a_S = self.assert_positive(+0.5 * v_S * self.step + self.nu) + a_E = self.assert_positive(-0.5 * u_E * self.step + self.nu) + a_W = self.assert_positive(+0.5 * u_W * self.step + self.nu) + a_N = self.assert_positive(-0.5 * v_N * self.step + self.nu) + a_S = self.assert_positive(+0.5 * v_S * self.step + self.nu) - a_n = 0.5 * self.step * (u_E - u_W + v_N - v_S) + 4 * self.nu - A_n = -self.step + a_n = 0.5 * self.step * (u_E - u_W + v_N - v_S) + 4 * self.nu + A_n = -self.step - self.d_n[i][j] = A_n / a_n + self.d_n[i][j] = A_n / a_n - self.v_star[i][j] = ( - a_E * self.v[i][j + 1] + - a_W * self.v[i][j - 1] + - a_N * self.v[i - 1][j] + - a_S * self.v[i + 1][j] - ) / a_n + self.d_n[i][j] * (self.p_star[i][j] - self.p_star[i + 1][j]) + self.v_star[i][j] = ( + a_E * self.v[i][j + 1] + + a_W * self.v[i][j - 1] + + a_N * self.v[i + 1][j] + + a_S * self.v[i - 1][j] + ) / a_n + self.d_n[i][j] * (self.p_star[i - 1][j] - self.p_star[i][j]) # p - p_n def apply_sides_boundary(self): for j in range(self.shape[1]): @@ -120,54 +120,75 @@ class SIMPLE: self.v_star[self.bfs_node_size[0]][j] = 0 def correct_pressure(self): - self.p_prime = self.allocate_field() - for i, j in self.grid(): - a_E = self.assert_positive(-self.d_e[i][j] * self.step) - a_W = self.assert_positive(-self.d_e[i][j-1] * self.step) - a_N = self.assert_positive(-self.d_n[i-1][j] * self.step) - a_S = self.assert_positive(-self.d_n[i][j] * self.step) - a_P = a_E + a_W + a_N + a_S - - self.b[i][j] = self.step * ( - -(self.u_star[i][j] - self.u_star[i][j-1]) - + (self.v_star[i][j] - self.v_star[i-1][j]) - ) - - self.p_prime[i][j] = ( - a_E * self.p_prime[i][j+1] + - a_W * self.p_prime[i][j-1] + - a_N * self.p_prime[i-1][j] + - a_S * self.p_prime[i+1][j] + - self.b[i][j] - ) / a_P + self.p_prime = np.zeros(shape=self.p.shape, dtype=float) + for i in range(1, self.p.shape[0] - 1): + for j in range(1, self.p.shape[1] - 1): + a_E = 0 if j == self.p.shape[1] - 1 else self.assert_positive(-self.d_e[i][j] * self.step) + a_W = 0 if j == 1 else self.assert_positive(-self.d_e[i][j+1] * self.step) + a_N = 0 if i == self.p.shape[0] - 1 else self.assert_positive(-self.d_n[i+1][j] * self.step) + a_S = 0 if i == 1 else self.assert_positive(-self.d_n[i][j] * self.step) + a_P = a_E + a_W + a_N + a_S + + self.b[i][j] = self.step * ( + -(self.u_star[i][j] - self.u_star[i][j+1]) + + (self.v_star[i+1][j] - self.v_star[i][j]) + ) + + self.p_prime[i][j] = ( + (a_E * self.p_prime[i][j+1] if a_E > 0 else 0) + + (a_W * self.p_prime[i][j-1] if a_W > 0 else 0) + + (a_N * self.p_prime[i+1][j] if a_N > 0 else 0) + + (a_S * self.p_prime[i-1][j] if a_S > 0 else 0) + + self.b[i][j] + ) / a_P self.p = self.p_star + self.p_prime * self.alpha self.p_star = self.p def correct_velocities(self): - for i, j in self.grid(): - self.u[i][j] = self.u_star[i][j] + self.d_e[i][j] * (self.p_prime[i][j + 1] - self.p_prime[i][j]) - self.v[i][j] = self.v_star[i][j] + self.d_n[i][j] * (self.p_prime[i][j] - self.p_prime[i + 1][j]) + for i in range(self.u.shape[0]): + for j in range(1, self.u.shape[1] - 1): + self.u[i][j] = self.u_star[i][j] + self.d_e[i][j] * (self.p_prime[i][j - 1] - self.p_prime[i][j]) + + for i in range(1, self.v.shape[0] - 1): + for j in range(self.v.shape[1]): + self.v[i][j] = self.v_star[i][j] + self.d_n[i][j] * (self.p_prime[i - 1][j] - self.p_prime[i][j]) def iterate(self): - self.apply_inflow_boundary() self.solve_momentum_equations() - self.apply_sides_boundary() - # self.apply_bfs_boundary() + # Boundary + self.u_star[:, 0] = -self.u_star[:, 1] + self.v_star[:, 0] = 0 + + self.u_star[:, -1] = -self.u_star[:, -2] + self.v_star[:, -1] = 0 + + self.u_star[-1, :] = 1 + self.v_star[-1, :] = -self.v_star[-2, :] + + self.u_star[0, :] = 0 + self.v_star[0, :] = -self.v_star[1, :] + + self.p_star[0, 0] = 0 self.correct_pressure() self.correct_velocities() - # Sides (magick wtf?) - for j in range(self.shape[1]): - self.v[1][j] = 0 - self.v[-2][j] = 0 + # Boundary enforce + self.u[:, 0] = -self.u[:, 1] + self.v[:, 0] = 0 + + self.u[:, -1] = -self.u[:, -2] + self.v[:, -1] = 0 + + self.u[-1, :] = 1 + self.v[-1, :] = -self.v[-2, :] - for i in range(self.shape[0]): - self.v[i][0] = 0 - self.v[i][1] = 0 + self.u[0, :] = 0 + self.v[0, :] = -self.v[1, :] + self.p[0, 0] = 0 def avg_error(self): return np.absolute(self.b).sum() |