def _staggered_curl_3d(self): """ Calculates the curl operator on a staggered three-dimensional field. The resulting vector field is a staggered grid. If the velocities of the vector potential were sampled at the lower faces of a cube, the resulting velocities are sampled at the centers of the upper edges. :param vector_potential: three-dimensional vector potential :return: three-dimensional staggered vector field """ kernel = np.zeros((2, 2, 2, 3, 3), np.float32) derivative = np.array([-1, 1]) # x-component: dz/dy - dy/dz kernel[0, :, 0, 2, 0] = derivative kernel[:, 0, 0, 1, 0] = -derivative # y-component: dx/dz - dz/dx kernel[:, 0, 0, 0, 1] = derivative kernel[0, 0, :, 2, 1] = -derivative # z-component: dy/dx - dx/dy kernel[0, 0, :, 1, 2] = derivative kernel[0, :, 0, 0, 2] = -derivative vector_potential = math.pad(self.staggered, [[0, 0], [0, 1], [0, 1], [0, 1], [0, 0]], "SYMMETRIC") vector_field = math.conv(vector_potential, kernel, padding="VALID") return StaggeredGrid(vector_field)
def staggered_curl_2d(grid, pad_width=(1, 2)): assert isinstance(grid, CenteredGrid) kernel = math.zeros((3, 3, 1, 2)) kernel[1, :, 0, 0] = [0, 1, -1] # y-component: - dz/dx kernel[:, 1, 0, 1] = [0, -1, 1] # x-component: dz/dy scalar_potential = grid.padded([pad_width, pad_width]).data vector_field = math.conv(scalar_potential, kernel, padding='valid') return StaggeredGrid(vector_field, box=grid.box)
def _staggered_curl_2d(self): kernel = np.zeros((2, 2, 1, 2), np.float32) derivative = np.array([-1, 1]) # x-component: dz/dy kernel[:, 0, 0, 0] = derivative # y-component: - dz/dx kernel[0, :, 0, 1] = -derivative scalar_potential = math.pad(self.staggered, [[0, 0], [0, 1], [0, 1], [0, 0]], "SYMMETRIC") vector_field = math.conv(scalar_potential, kernel, padding="VALID") return StaggeredGrid(vector_field)
def _conv_laplace_3d(tensor): kernel = np.zeros((3, 3, 3, 1, 1), np.float32) kernel[1, 1, 1, 0, 0] = -6 kernel[(0, 1, 1, 1, 1, 2), (1, 0, 2, 1, 1, 1), (1, 1, 1, 0, 2, 1), 0, 0] = 1 return math.conv(tensor, kernel, padding="VALID")