def initialize_f_neq(self): """Initialize the distribution function values. The f^(1) contributions are approximated by finite differences. See Krüger et al. (2017). """ rho = self.lattice.rho(self.f) u = self.lattice.u(self.f) grad_u0 = torch_gradient(u[0], dx=1, order=6)[None, ...] grad_u1 = torch_gradient(u[1], dx=1, order=6)[None, ...] S = torch.cat([grad_u1, grad_u0]) if (self.lattice.D == 3): grad_u2 = torch_gradient(u[2], dx=1, order=6)[None, ...] S = torch.cat([S, grad_u2]) Pi_1 = -1.0 * self.flow.units.relaxation_parameter_lu * rho * S / self.lattice.cs**2 Q = torch.einsum('ia,ib->iab', self.lattice.e, self.lattice.e) - torch.eye( self.lattice.D, device=self.lattice.device) * self.lattice.cs**2 Pi_1_Q = torch.einsum('ab...,iab->i...', Pi_1, Q) fneq = torch.einsum('i,i...->i...', self.lattice.w, Pi_1_Q) feq = self.lattice.equilibrium(rho, u) self.f = feq + fneq
def test_divergence(stencil, dtype_device): dtype, device = dtype_device lattice = Lattice(stencil, dtype=dtype, device=device) flow = DecayingTurbulence(50, 1, 0.05, lattice=lattice, ic_energy=0.5) collision = BGKCollision(lattice, tau=flow.units.relaxation_parameter_lu) streaming = StandardStreaming(lattice) simulation = Simulation(flow=flow, lattice=lattice, collision=collision, streaming=streaming) ekin = flow.units.convert_incompressible_energy_to_pu( torch.sum(lattice.incompressible_energy( simulation.f))) * flow.units.convert_length_to_pu(1.0)**lattice.D u0 = flow.units.convert_velocity_to_pu(lattice.u(simulation.f)[0]) u1 = flow.units.convert_velocity_to_pu(lattice.u(simulation.f)[1]) dx = flow.units.convert_length_to_pu(1.0) grad_u0 = torch_gradient(u0, dx=dx, order=6).cpu().numpy() grad_u1 = torch_gradient(u1, dx=dx, order=6).cpu().numpy() divergence = np.sum(grad_u0[0] + grad_u1[1]) if lattice.D == 3: u2 = flow.units.convert_velocity_to_pu(lattice.u(simulation.f)[2]) grad_u2 = torch_gradient(u2, dx=dx, order=6).cpu().numpy() divergence += np.sum(grad_u2[2]) assert (flow.ic_energy == pytest.approx(lattice.convert_to_numpy(ekin), rel=1)) assert (0 == pytest.approx(divergence, abs=2e-3))
def test_torch_gradient_3d(order): lattice = Lattice( D3Q27, device='cpu', ) flow = TaylorGreenVortex3D(resolution=100, reynolds_number=1, mach_number=0.05, lattice=lattice) grid = flow.grid p, u = flow.initial_solution(grid) dx = flow.units.convert_length_to_pu(1.0) u0_grad = torch_gradient(lattice.convert_to_tensor(u[0]), dx=dx, order=order).numpy() u0_grad_np = np.array(np.gradient(u[0], dx)) u0_grad_analytic = np.array([ np.cos(grid[0]) * np.cos(grid[1]) * np.cos(grid[2]), np.sin(grid[0]) * np.sin(grid[1]) * (-np.cos(grid[2])), np.sin(grid[0]) * (-np.cos(grid[1])) * np.sin(grid[2]) ]) assert np.allclose(u0_grad_analytic, u0_grad, rtol=0.0, atol=1e-3) assert np.allclose(u0_grad_np[:, 2:-2, 2:-2, 2:-2], u0_grad[:, 2:-2, 2:-2, 2:-2], rtol=0.0, atol=1e-3)
def test_torch_gradient_2d(order): lattice = Lattice(D2Q9, device='cpu', ) flow = TaylorGreenVortex2D(resolution=100, reynolds_number=1, mach_number=0.05, lattice=lattice) grid = flow.grid p, u = flow.initial_solution(grid) dx = flow.units.convert_length_to_pu(1.0) u0_grad = torch_gradient(lattice.convert_to_tensor(u[0]), dx=dx, order=order).numpy() u0_grad_np = np.array(np.gradient(u[0], dx)) u0_grad_analytic = np.array([ -np.sin(grid[0]) * np.sin(grid[1]), np.cos(grid[0]) * np.cos(grid[1]), ]) assert (u0_grad_analytic == pytest.approx(u0_grad, rel=0.0, abs=1e-3)) assert (u0_grad_np[:, 2:-2, 2:-2] == pytest.approx(u0_grad[:, 2:-2, 2:-2], rel=0.0, abs=1e-3))
def test_torch_gradient_2d(order): lattice = Lattice( D2Q9, device='cpu', ) flow = TaylorGreenVortex2D(resolution=100, reynolds_number=1, mach_number=0.05, lattice=lattice) grid = flow.grid p, u = flow.initial_solution(grid) dx = grid[0][0][1] - grid[0][0][0] u0_grad = torch_gradient(lattice.convert_to_tensor(u[0]), dx=dx, order=order).numpy() u0_grad_analytic = np.array([ -np.sin(grid[0]) * np.sin(grid[1]), np.cos(grid[0]) * np.cos(grid[1]), ]) assert (u0_grad_analytic[0, 1, :] == pytest.approx(u0_grad[0, 1, :], rel=2))