def calc_t(t, uvwf, rho_cap, kappa, dt, dxyz, obst): # -------------------------------------------------------------------------- """ Docstring. """ # Unpack tuple(s) dx, dy, dz = dxyz # Fetch the resolution rc = t.val.shape # Discretize the diffusive part A_t, b_t = create_matrix(t, rho_cap / dt, kappa, dxyz, obst, 'n') # The advective fluxes c_t = advection(rho_cap, t, uvwf, dxyz, dt, 'minmod') # Innertial term for enthalpy i_t = t.old * rho_cap * dx * dy * dz / dt # The entire source term f_t = b_t - c_t + i_t # Solve for temperature res0 = bicgstab(A_t, reshape(f_t, prod(rc)), tol=TOL) t.val[:] = reshape(res0[0], rc) adj_n_bnds(t) return # end of function
def calc_p(p, uvwf, rho, dt, dxyz, obst): """ Calculating the Pressure. """ # ------------------------------------------------------------------------- # Fetch the resolution rc = p.val.shape # Create linear system A_p, b_p = create_matrix(p, zeros(rc), dt/rho, dxyz, obst, 'n') # Compute the source for the pressure. Important: don't send "obst" # as a parameter here, because you don't want to take it into # account at this stage. After velocity corrections, you should. b_p = vol_balance(uvwf, dxyz, zeros(rc)) print('Maximum volume error before correction: %12.5e' % abs(b_p).max()) print('Volume imbalance before correction : %12.5e' % b_p.sum()) # Solve for pressure res = bicgstab(A_p, reshape(b_p, prod(rc)), tol=TOL) p.val[:] = reshape(res[0], rc) print("res[1] = ", res[1]) # Anchor it to values around zero (the absolute value of pressure # correction can get really volatile. Although it is in prinicple not # important for incompressible flows, it is ugly for post-processing. p.val[:] = p.val[:] - p.val.mean() # Set to zero in obstacle (it can get strange # values during the iterative solution procedure) if obst.any() != 0: p.val[:] = obst_zero_val(p.pos, p.val, obst) # Finally adjust the boundary values p = adj_n_bnds(p) return # end of function
def main(show_plot=True): """ Docstring. """ # ========================================================================= # # Define problem # # ========================================================================= # Node coordinates xn = nodes(0, 10, 300) yn = nodes(0, 1, 40, 1 / 500, 1 / 500) zn = nodes(0, 3, 3) # Cell coordinates xc = avg(xn) yc = avg(yn) zc = avg(zn) # Cell dimensions nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn) # Set physical properties rho = zeros(rc) mu = zeros(rc) kappa = zeros(rc) cap = zeros(rc) rho[:, :, :] = 1. mu[:, :, :] = 0.1 kappa[:, :, :] = 0.15 cap[:, :, :] = 1.0 # Time-stepping parameters dt = 0.003 # time step ndt = 1500 # number of time steps # Create unknowns; names, positions and sizes uf = create_unknown('face-u-vel', X, ru, DIRICHLET) vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) t = create_unknown('temperature', C, rc, NEUMANN) p = create_unknown('pressure', C, rc, NEUMANN) # Specify boundary conditions uf.bnd[W].typ[:1, :, :] = DIRICHLET for k in range(0, nz): uf.bnd[W].val[:1, :, k] = par(1.0, yn) uf.bnd[E].typ[:1, :, :] = OUTLET uf.bnd[E].val[:1, :, :] = 1.0 for j in (B, T): uf.bnd[j].typ[:] = NEUMANN vf.bnd[j].typ[:] = NEUMANN wf.bnd[j].typ[:] = NEUMANN t.bnd[W].typ[:1, :, :] = DIRICHLET for k in range(0, nz): t.bnd[W].val[:1, :, k] = 1.0 - yc t.bnd[S].typ[:, :1, :] = DIRICHLET t.bnd[S].val[:, :1, :] = +1.0 t.bnd[N].typ[:, :1, :] = DIRICHLET t.bnd[N].val[:, :1, :] = 0.0 adj_n_bnds(t) adj_n_bnds(p) # Specify initial conditions uf.val[:, :, :] = 1.0 t.val[:, :, :] = 0 obst = zeros(rc) # ========================================================================= # # Solution algorithm # # ========================================================================= # ----------- # # Time loop # # ----------- for ts in range(1, ndt + 1): print_time_step(ts) # ------------------ # Store old values # ------------------ t.old[:] = t.val[:] uf.old[:] = uf.val[:] vf.old[:] = vf.val[:] wf.old[:] = wf.val[:] # ------------------------ # Temperature (enthalpy) # ------------------------ calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst) # ----------------------- # Momentum conservation # ----------------------- ef = zeros(ru), 150.0 * avg(Y, t.val), zeros(rw) calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \ zeros(rc), ef, dt, (dx, dy, dz), obst) # ---------- # Pressure # ---------- calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) # --------------------- # Velocity correction # --------------------- corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) # Compute volume balance for checking err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) print('Maximum volume error after correction: %12.5e' % abs(err).max()) # Check the CFL number too cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) print('Maximum CFL number: %12.5e' % cfl) # ===================================================================== # # Visualisation # # ===================================================================== if show_plot: if ts % 150 == 0: plot_isolines(t.val, (uf, vf, wf), (xn, yn, zn), Z) plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z)
def main(show_plot=True): """Example """ #========================================================================== # # Define problem # #========================================================================== # Node coordinates xn = nodes(0, 1, 256) yn = nodes(0, 0.125, 32) zn = nodes(0, 0.125, 4) # Cell coordinates xc = avg(xn) yc = avg(yn) zc = avg(zn) # Cell dimensions nx, ny, nz, \ dx, dy, dz, \ rc, ru, rv, rw = cartesian_grid(xn, yn, zn) # Set physical properties rho, mu, cap, kappa = properties_for_air(rc) # Time-stepping parameters dt = 0.002 # time step ndt = 5000 # number of time steps # Create unknowns; names, positions and sizes uf = create_unknown('face-u-vel', X, ru, DIRICHLET) vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) p = create_unknown('pressure', C, rc, NEUMANN) # Specify boundary conditions uf.bnd[W].typ[:1, :, :] = DIRICHLET for k in range(0, nz): uf.bnd[W].val[:1, :, k] = par(0.1, yn) uf.bnd[E].typ[:1, :, :] = OUTLET for j in (B, T): uf.bnd[j].typ[:] = NEUMANN vf.bnd[j].typ[:] = NEUMANN wf.bnd[j].typ[:] = NEUMANN adj_n_bnds(p) obst = zeros(rc) for j in range(0, 24): for i in range(64 + j, 64 + 24): for k in range(0, nz): obst[i, j, k] = 1 # ========================================================================= # # Solution algorithm # # ========================================================================= # ----------- # # Time loop # # ----------- for ts in range(1, ndt + 1): print_time_step(ts) # ------------------ # Store old values # ------------------ uf.old[:] = uf.val[:] vf.old[:] = vf.val[:] wf.old[:] = wf.val[:] # ----------------------- # Momentum conservation # ----------------------- ef = zeros(ru), zeros(rv), zeros(rw) calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \ zeros(rc), ef, dt, (dx, dy, dz), obst) # ---------- # Pressure # ---------- calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) # --------------------- # Velocity correction # --------------------- corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) # Compute volume balance for checking err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) print('Maximum volume error after correction: %12.5e' % abs(err).max()) # Check the CFL number too cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) print('Maximum CFL number: %12.5e' % cfl) # ===================================================================== # # Visualisation # # ===================================================================== if show_plot: if ts % 20 == 0: plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z)
def main(show_plot=True): """ Docstring. """ # ========================================================================= # # Define problem # # ========================================================================= # Node coordinates xn = nodes(0, 1.25, 256) yn = nodes(0, 0.125, 32) zn = nodes(0, 0.125, 32) # Cell coordinates xc = avg(xn) yc = avg(yn) zc = avg(zn) # Cell dimensions nx, ny, nz, \ dx, dy, dz, \ rc, ru, rv, rw = cartesian_grid(xn, yn, zn) # Set physical properties rho, mu, cap, kappa = properties_for_air(rc) # Time-stepping parameters dt = 0.005 # time step ndt = 2000 # number of time steps # Create unknowns; names, positions and sizes uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) uf = create_unknown('face-u-vel', X, ru, DIRICHLET) vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) p = create_unknown('pressure', C, rc, NEUMANN) # Specify boundary conditions uc.bnd[W].typ[:1, :, :] = DIRICHLET uc.bnd[W].val[:1, :, :] = 0.1 * outer(par(1.0, yn), par(1.0, zn)) uc.bnd[E].typ[:1, :, :] = OUTLET for j in (B, T): uc.bnd[j].typ[:] = NEUMANN vc.bnd[j].typ[:] = NEUMANN wc.bnd[j].typ[:] = NEUMANN adj_n_bnds(p) # Create obstacles obst = zeros(rc) class key: """ Class Docstring. """ ip = -1 im = -1 jp = -1 jm = -1 kp = -1 km = -1 block = (key(), key(), key(), key()) th = 5 block[0].im = 3 * nx / 16 # i minus block[0].ip = block[0].im + th # i plus block[0].jm = 0 # j minus block[0].jp = 3 * ny / 4 # j plus block[0].km = 0 # k minus block[0].kp = 3 * ny / 4 # k plus block[1].im = 5 * nx / 16 # i minus block[1].ip = block[1].im + th # i plus block[1].jm = ny / 4 # j minus block[1].jp = ny # j plus block[1].km = ny / 4 # k minus block[1].kp = ny # k plus block[2].im = 7 * nx / 16 # i minus block[2].ip = block[2].im + th # i plus block[2].jm = 0 # j minus block[2].jp = 3 * ny / 4 # j plus block[2].km = 0 # k minus block[2].kp = 3 * ny / 4 # k plus block[3].im = 9 * nx / 16 # i minus block[3].ip = block[3].im + th # i plus block[3].jm = ny / 4 # j minus block[3].jp = ny # j plus block[3].km = ny / 4 # k minus block[3].kp = ny # k plus for o in range(0, 4): for i in range(floor(block[o].im), floor(block[o].ip)): for j in range(floor(block[o].jm), floor(block[o].jp)): for k in range(floor(block[o].km), floor(block[o].kp)): obst[i, j, k] = 1 # ========================================================================= # # Solution algorithm # # ========================================================================= # ----------- # # Time loop # # ----------- for ts in range(1, ndt + 1): print_time_step(ts) # ------------------ # Store old values # ------------------ uc.old[:] = uc.val[:] vc.old[:] = vc.val[:] wc.old[:] = wc.val[:] # ----------------------- # Momentum conservation # ----------------------- ef = zeros(rc), zeros(rc), zeros(rc) calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, zeros(rc), ef, dt, (dx, dy, dz), obst) # ---------- # Pressure # ---------- calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) # --------------------- # Velocity correction # --------------------- corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst) corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) # Compute volume balance for checking err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) print('Maximum volume error after correction: %12.5e' % abs(err).max()) # Check the CFL number too cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz)) print('Maximum CFL number: %12.5e' % cfl) # ===================================================================== # # Visualisation # # ===================================================================== if show_plot: if ts % 20 == 0: plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Y) plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Z)