def elbm_d3q15_equilibrium(grid): """ Form of equilibrium defined in PRL 97, 010201 (2006). See also Chikatamarla, PhD Thesis, Eq. (5.7), (5.8). """ rho = S.rho prefactor = Symbol('prefactor') coeff1 = Symbol('coeff1') coeff2 = Symbol('coeff2') coeff3 = Symbol('coeff3') vsq = Symbol('vsq') vx, vy, vz = grid.v lvars = [] lvars.append(Eq(vsq, grid.v.dot(grid.v))) lvars.append(Eq(prefactor, poly_factorize( rho * (1 - 3 * vsq / 2 + 9 * vsq**2 / 8 + Rational(27, 16) * (-vsq**3 + 2 * (vy**2 + vz**2) * (vsq * vx**2 + vy**2 * vz**2) + 20 * vx**2 * vy**2 * vz**2) + Rational(81, 128) * vsq**4 + Rational(81, 32) * (vx**8 + vy**8 + vz**8 - 36 * vx**2 * vy**2 * vz**2 * vsq - vx**4 * vy**4 - vy**4 * vz**4 - vx**4 * vz**4))))) cfs = [coeff1, coeff2, coeff3] for i, coeff in enumerate(cfs): tmp = (1 + 3 * grid.v[i] + 9 * grid.v[i]**2 / 2 + 9 * grid.v[i]**3 / 2 + 27 * grid.v[i]**4 / 8) # Cyclic permutation. x = i y = (i + 1) % 3 z = (i + 2) % 3 tmp += Rational(27, 8) * (grid.v[x]**5 - 4 * grid.v[x] * grid.v[y]**2 * grid.v[z]**2) tmp += Rational(81, 16) * (grid.v[x]**6 - 8 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2) tmp += Rational(81, 16) * (grid.v[x]**7 - 10 * grid.v[x]**3 * grid.v[y]**2 * grid.v[z]**2 + 2 * grid.v[x] * grid.v[y]**2 * grid.v[z]**2 * vsq) tmp += Rational(243, 128) * (grid.v[x]**8 + 16 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2 * (grid.v[y]**2 + grid.v[z]**2)) lvars.append(Eq(coeff, poly_factorize(tmp))) out = [] for ei, weight in zip(grid.basis, grid.entropic_weights): t = prefactor * weight for j, comp in enumerate(ei): t *= cfs[j]**comp out.append(t) return EqDef(out, lvars)
def bgk_equilibrium(grid, config, rho=None, rho0=None, order=2): """Get expressions for the BGK equilibrium distribution. :param grid: the grid class to be used """ out = [] if rho is None: rho = S.rho if rho0 is None: if config.incompressible: rho0 = S.rho0 elif config.minimize_roundoff: rho0 = rho + 1.0 else: rho0 = rho for ei, weight in zip(grid.basis, grid.weights): h = (ei.dot(grid.v) / grid.cssq + ei.dot(grid.v)**2 / grid.cssq**2 / 2 - grid.v.dot(grid.v) / 2 / grid.cssq) # Aidun, Clausen; Latice-Boltzmann Method for Complex Flows # Note: this does not seem to recover the 1st moment in the unit test! # if order > 2: # h += (ei.dot(grid.v)**3 / grid.cssq**3 / 2 - # ei.dot(grid.v) * grid.v.dot(grid.v) / grid.cssq**2 / 2) out.append(weight * (rho + rho0 * poly_factorize(h))) return EqDef(out, local_vars=[])
def bgk_equilibrium(grid, config, rho=None, rho0=None, order=2): """Get expressions for the BGK equilibrium distribution. :param grid: the grid class to be used """ out = [] if rho is None: rho = S.rho if rho0 is None: if config.incompressible: rho0 = S.rho0 elif config.minimize_roundoff: rho0 = rho + 1.0 else: rho0 = rho for ei, weight in zip(grid.basis, grid.weights): h = (ei.dot(grid.v) / grid.cssq + ei.dot(grid.v)**2 / grid.cssq**2 / 2 - grid.v.dot(grid.v) / 2 / grid.cssq) if order > 2: h += (ei.dot(grid.v)**3 / grid.cssq**3 / 2 - ei.dot(grid.v) * grid.v.dot(grid.v) / grid.cssq**2 / 2) out.append(weight * (rho + rho0 * poly_factorize(h))) return EqDef(out, local_vars=[])
def _init_mrt_equilibrium(cls): cls.mrt_equilibrium = [] cls.mrt_eq_symbols = [] c1 = -2 # Name -> index map. n2i = {} for i, name in enumerate(cls.mrt_names): n2i[name] = i inv_tau = Symbol('inv_tau') cls.mrt_eq_symbols.append( Eq(inv_tau, 1 / (0.5 + S.visc * Rational(12, 2 - c1)))) cls.mrt_collision[n2i['pxx']] = inv_tau cls.mrt_collision[n2i['pxy']] = cls.mrt_collision[n2i['pxx']] vec_rho = cls.mrt_matrix[n2i['rho'], :] vec_mx = cls.mrt_matrix[n2i['mx'], :] vec_my = cls.mrt_matrix[n2i['my'], :] # We choose the form of the equilibrium distributions and the # optimal parameters as shows in the PhysRevE.61.6546 paper about # MRT in 2D. for i, name in enumerate(cls.mrt_names): if cls.mrt_collision[i] == 0: cls.mrt_equilibrium.append(0) continue vec_e = cls.mrt_matrix[i, :] if name == 'en': t = (Rational(1, vec_e.dot(vec_e)) * (-8 * vec_rho.dot(vec_rho) * S.rho + 18 * (vec_mx.dot(vec_mx) * cls.mx**2 + vec_my.dot(vec_my) * cls.my**2))) elif name == 'ens': # The 4 and -18 below are freely adjustable parameters. t = (Rational(1, vec_e.dot(vec_e)) * (4 * vec_rho.dot(vec_rho) * S.rho + -18 * (vec_mx.dot(vec_mx) * cls.mx**2 + vec_my.dot(vec_my) * cls.my**2))) elif name == 'ex': t = Rational( 1, vec_e.dot(vec_e)) * (c1 * vec_mx.dot(vec_mx) * cls.mx) elif name == 'ey': t = Rational( 1, vec_e.dot(vec_e)) * (c1 * vec_my.dot(vec_my) * cls.my) elif name == 'pxx': t = (Rational(1, vec_e.dot(vec_e)) * Rational(2, 3) * (vec_mx.dot(vec_mx) * cls.mx**2 - vec_my.dot(vec_my) * cls.my**2)) elif name == 'pxy': t = (Rational(1, vec_e.dot(vec_e)) * Rational(2, 3) * (math.sqrt(vec_mx.dot(vec_mx) * vec_my.dot(vec_my)) * cls.mx * cls.my)) t = sym_codegen.poly_factorize(t) cls.mrt_equilibrium.append(t)
def _init_mrt_equilibrium(cls): cls.mrt_equilibrium = [] cls.mrt_eq_symbols = [] c1 = -2 # Name -> index map. n2i = {} for i, name in enumerate(cls.mrt_names): n2i[name] = i inv_tau = Symbol('inv_tau') cls.mrt_eq_symbols.append(Eq(inv_tau, 1 / (0.5 + S.visc * Rational(12, 2-c1)))) cls.mrt_collision[n2i['pxx']] = inv_tau cls.mrt_collision[n2i['pxy']] = cls.mrt_collision[n2i['pxx']] vec_rho = cls.mrt_matrix[n2i['rho'],:] vec_mx = cls.mrt_matrix[n2i['mx'],:] vec_my = cls.mrt_matrix[n2i['my'],:] # We choose the form of the equilibrium distributions and the # optimal parameters as shows in the PhysRevE.61.6546 paper about # MRT in 2D. for i, name in enumerate(cls.mrt_names): if cls.mrt_collision[i] == 0: cls.mrt_equilibrium.append(0) continue vec_e = cls.mrt_matrix[i,:] if name == 'en': t = (Rational(1, vec_e.dot(vec_e)) * (-8*vec_rho.dot(vec_rho)*S.rho + 18*(vec_mx.dot(vec_mx)*cls.mx**2 + vec_my.dot(vec_my)*cls.my**2))) elif name == 'ens': # The 4 and -18 below are freely adjustable parameters. t = (Rational(1, vec_e.dot(vec_e)) * (4*vec_rho.dot(vec_rho)*S.rho + -18*(vec_mx.dot(vec_mx)*cls.mx**2 + vec_my.dot(vec_my)*cls.my**2))) elif name == 'ex': t = Rational(1, vec_e.dot(vec_e)) * (c1 * vec_mx.dot(vec_mx)*cls.mx) elif name == 'ey': t = Rational(1, vec_e.dot(vec_e)) * (c1 * vec_my.dot(vec_my)*cls.my) elif name == 'pxx': t = (Rational(1, vec_e.dot(vec_e)) * Rational(2, 3) * (vec_mx.dot(vec_mx)*cls.mx**2 - vec_my.dot(vec_my)*cls.my**2)) elif name == 'pxy': t = (Rational(1, vec_e.dot(vec_e)) * Rational(2, 3) * (math.sqrt(vec_mx.dot(vec_mx) * vec_my.dot(vec_my)) * cls.mx * cls.my)) t = sym_codegen.poly_factorize(t) cls.mrt_equilibrium.append(t)
def alpha_series(): """See Phys Rev Lett 97, 010201 (2006) for the expression.""" a1 = Symbol('a1') a2 = Symbol('a2') a3 = Symbol('a3') a4 = Symbol('a4') alpha = sym_codegen.poly_factorize(2 - 4 * a2 / a1 + 16 * a2**2 / a1**2 - 8 * a3 / a1 + 80 * a2 * a3 / a1**2 - 80 * a2**3 / a1**3 - 16 * a4 / a1) return alpha
def shallow_water_equilibrium(grid, config): """Get expressions for the BGK equilibrium distribution for the shallow water equation.""" if grid.dim != 2 or grid.Q != 9: raise TypeError('Shallow water equation requires the D2Q9 grid.') out = [S.rho - grid.weights[0] * S.rho * ( Rational(15, 8) * S.gravity * S.rho - 3 * grid.v.dot(grid.v))] for ei, weight in zip(grid.basis[1:], grid.weights[1:]): out.append(weight * ( S.rho * poly_factorize(Rational(3,2) * S.rho * S.gravity + 3*ei.dot(grid.v) + Rational(9,2) * (ei.dot(grid.v))**2 - Rational(3, 2) * grid.v.dot(grid.v)))) return EqDef(out, local_vars=[])
def noneq_bb(grid, orientation, eq): normal = grid.dir_to_vec(orientation) known, unknown = _get_known_dists(grid, normal) ret = [] # Bounce-back of the non-equilibrium parts. for i in unknown: oi = grid.idx_opposite[i] ret.append((Symbol('fi->%s' % grid.idx_name[i]), Symbol('fi->%s' % grid.idx_name[oi]) - eq[oi] + eq[i])) for i in range(0, len(ret)): t = sym_codegen.poly_factorize(ret[i][1]) ret[i] = (ret[i][0], t) return ret
def guo_external_force(grid, grid_num=0): """Gets expressions for the external body force correction in the BGK model. This implements the external force as in Eq. 20 from PhysRevE 65, 046308. :param grid: the grid class to be used :rtype: list of sympy expressions (in the same order as the current grid's basis) """ pref = Symbol('pref') ea = accel_vector(grid, grid_num) ret = [] for i, ei in enumerate(grid.basis): ret.append(pref * grid.weights[i] * poly_factorize( (ei - grid.v + ei.dot(grid.v) * ei * 3).dot(ea))) return ret
def guo_external_force(grid, grid_num=0): """Gets expressions for the external body force correction in the BGK model. This implements the external force as in Eq. 20 from PhysRevE 65, 046308. :param grid: the grid class to be used :rtype: list of sympy expressions (in the same order as the current grid's basis) """ pref = Symbol('pref') ea = accel_vector(grid, grid_num) ret = [] for i, ei in enumerate(grid.basis): ret.append(pref * grid.weights[i] * poly_factorize((ei - grid.v + ei.dot(grid.v)*ei*3).dot(ea))) return ret
def elbm_d3q15_equilibrium(grid, order=8): """ Form of equilibrium defined in PRL 97, 010201 (2006). See also Chikatamarla, PhD Thesis, Eq. (5.7), (5.8). """ rho = S.rho prefactor = Symbol('chi') coeff1 = Symbol('zeta_x') coeff2 = Symbol('zeta_y') coeff3 = Symbol('zeta_z') vsq = Symbol('vsq') vx, vy, vz = grid.v o = [(1 if i <= order else 0) for i in range(0, 9)] lvars = [] lvars.append(Eq(vsq, grid.v.dot(grid.v))) lvars.append(Eq(prefactor, poly_factorize( rho * (1 - o[2] * Rational(3, 2) * vsq + o[4] * Rational(9, 8) * vsq**2 + o[6] * Rational(27, 16) * (-vsq**3 + 2 * (vy**2 + vz**2) * (vsq * vx**2 + vy**2 * vz**2) + 20 * vx**2 * vy**2 * vz**2) + o[8] * (Rational(81, 128) * vsq**4 + Rational(81, 32) * ( vx**8 + vy**8 + vz**8 - 36 * vx**2 * vy**2 * vz**2 * vsq - vx**4 * vy**4 - vy**4 * vz**4 - vx**4 * vz**4)))))) cfs = [coeff1, coeff2, coeff3] for i, coeff in enumerate(cfs): tmp = (1 + o[1] * 3 * grid.v[i] + o[2] * Rational(9, 2) * grid.v[i]**2 + o[3] * Rational(9, 2) * grid.v[i]**3 + o[4] * Rational(27, 8) * grid.v[i]**4) # Cyclic permutation. x = i y = (i + 1) % 3 z = (i + 2) % 3 tmp += o[5] * Rational(27, 8) * ( grid.v[x]**5 - 4 * grid.v[x] * grid.v[y]**2 * grid.v[z]**2) tmp += o[6] * Rational(81, 16) * ( grid.v[x]**6 - 8 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2) tmp += o[7] * Rational(81, 16) * ( grid.v[x]**7 - 10 * grid.v[x]**3 * grid.v[y]**2 * grid.v[z]**2 + 2 * grid.v[x] * grid.v[y]**2 * grid.v[z]**2 * vsq) tmp += o[8] * Rational(243, 128) * ( grid.v[x]**8 + 16 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2 * (grid.v[y]**2 + grid.v[z]**2)) lvars.append(Eq(coeff, poly_factorize(tmp))) out = [] for ei, weight in zip(grid.basis, grid.entropic_weights): t = prefactor * weight for j, comp in enumerate(ei): t *= cfs[j]**comp out.append(t) return EqDef(out, lvars)
def elbm_d3q19_equilibrium(grid, order=8): rho = S.rho prefactor = Symbol('chi') coeff1 = Symbol('zeta_x') coeff2 = Symbol('zeta_y') coeff3 = Symbol('zeta_z') vsq = Symbol('vsq') vx, vy, vz = grid.v o = [(1 if i <= order else 0) for i in range(0, 9)] lvars = [] lvars.append(Eq(vsq, grid.v.dot(grid.v))) lvars.append(Eq(prefactor, poly_factorize( rho * (1 - o[2] * Rational(3, 2) * vsq + o[4] * Rational(9, 8) * vsq**2 - o[6] * Rational(27, 16) * (vx**6 + vx**4 * (vy**2 + vz**2) + (vy**2 + vz**2) * (vy**4 + vz**4) + vx**2 * (vy**4 + 12 * vy**2 * vz**2 + vz**4)) + o[8] * Rational(81, 128) * (5 * vx**8 + 5 * vy**8 + 4 * vy**6 * vz**2 + 2 * vy**4 * vz**4 + 4 * vy**2 * vz**6 + 5 * vz**8 + 4 * vx**6 * (vy**2 + vz**2) + 4 * vx**2 * (vy**2 + vz**2) * ( vy**4 + 17 * vy**2 * vz**2 + vz**4) + 2 * vx**4 * (vy**4 + 36 * vy**2 * vz**2 + vz**4)))))) cfs = [coeff1, coeff2, coeff3] for i, coeff in enumerate(cfs): tmp = (1 + o[1] * 3 * grid.v[i] + o[2] * Rational(9, 2) * grid.v[i]**2 + o[3] * Rational(9, 2) * grid.v[i]**3 + o[4] * Rational(27, 8) * grid.v[i]**4) # Cyclic permutation. x = i y = (i + 1) % 3 z = (i + 2) % 3 tmp += o[5] * Rational(27, 8) * ( grid.v[x]**5 + 2 * grid.v[x] * grid.v[y]**2 * grid.v[z]**2) tmp += o[6] * Rational(81, 16) * ( grid.v[x]**6 + 4 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2) tmp += o[7] * Rational(81, 16) * ( grid.v[x] * (grid.v[x]**6 + 4 * grid.v[x]**2 * grid.v[y]**2 * grid.v[z]**2 - grid.v[y]**2 * grid.v[z]**2 * (grid.v[y]**2 + grid.v[z]**2))) tmp += o[8] * Rational(243, 128) * ( grid.v[x]**2 * (grid.v[x]**6 - 8 * grid.v[y]**2 * grid.v[z]**2 * ( grid.v[y]**2 + grid.v[z]**2))) lvars.append(Eq(coeff, poly_factorize(tmp))) out = [] for ei, weight in zip(grid.basis, grid.entropic_weights): t = prefactor * weight for j, comp in enumerate(ei): t *= cfs[j]**comp out.append(t) return EqDef(out, lvars)