def test_basic(): lmax = 10 nside = 8 rank = MPI.COMM_WORLD.Get_rank() ms = np.arange(rank, lmax + 1, MPI.COMM_WORLD.Get_size(), dtype=np.int32) order = libsharp.packed_real_order(lmax, ms=ms) grid = libsharp.healpix_grid(nside) alm = np.zeros(order.local_size()) if rank == 0: alm[0] = 1 elif rank == 1: alm[0] = 1 map = libsharp.synthesis(grid, order, np.repeat(alm[None, None, :], 3, 0), comm=MPI.COMM_WORLD) assert np.all(map[2, :] == map[1, :]) and np.all(map[1, :] == map[0, :]) map = map[0, 0, :] if rank == 0: healpy.mollzoom(map) from matplotlib.pyplot import show show()
def distribute_rings_libsharp(mpi_comm, nside, lmax): """Create a libsharp map distribution based on rings Build a libsharp grid object to distribute a HEALPix map balancing North and South distribution of rings to achieve the best performance on Harmonic Transforms Returns the grid object and the pixel indices array in RING ordering Parameters --------- mpi_comm : mpi4py.MPI.Comm mpi4py communicator nside : int nside of the map Returns ------- grid : libsharp.healpix_grid libsharp object that includes metadata about HEALPix distributed rings local_pix : np.ndarray integer array of local pixel indices in the current MPI process in RING ordering """ import libsharp nrings = 4 * nside - 1 # four missing pixels # ring indices are 1-based ring_indices_emisphere = np.arange(2 * nside, dtype=np.int32) + 1 local_ring_indices = ring_indices_emisphere[mpi_comm.rank::mpi_comm.size] # to improve performance, symmetric rings north/south need to be in the same rank # therefore we use symmetry to create the full ring indexing if local_ring_indices[-1] == 2 * nside: # has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1]) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1]) libsharp_grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(int)) local_npix = libsharp_grid.local_size() local_pixels = expand_pix(startpix, ringpix, local_npix).astype(int) local_m_indices = np.arange(mpi_comm.rank, lmax + 1, mpi_comm.size, dtype=np.int32) libsharp_order = libsharp.packed_real_order(lmax, ms=local_m_indices) return local_pixels, libsharp_grid, libsharp_order
def distribute_rings(nside, rank, n_mpi_processes): """Create a libsharp map distribution based on rings Build a libsharp grid object to distribute a HEALPix map balancing North and South distribution of rings to achieve the best performance on Harmonic Transforms Returns the grid object and the pixel indices array in RING ordering Parameters --------- nside : int HEALPix NSIDE parameter of the distributed map rank, n_mpi_processes, ints rank of the current MPI process and total number of processes Returns ------- grid : libsharp.healpix_grid libsharp object that includes metadata about HEALPix distributed rings local_pix : np.ndarray integer array of local pixel indices in the current MPI process in RING ordering """ if libsharp is None: raise RuntimeError('libsharp not available') autotimer = timing.auto_timer() nrings = 4 * nside - 1 # four missing pixels # ring indices are 1-based ring_indices_emisphere = np.arange(2 * nside, dtype=np.int32) + 1 local_ring_indices = ring_indices_emisphere[rank::n_mpi_processes] # to improve performance, symmetric rings north/south need to be in the same rank # therefore we use symmetry to create the full ring indexing if local_ring_indices[-1] == 2 * nside: # has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1] ) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1] ) grid = libsharp.healpix_grid(nside, rings=local_ring_indices) return grid, local_ring_indices
def distribute_rings(nside, rank, n_mpi_processes): """Create a libsharp map distribution based on rings Build a libsharp grid object to distribute a HEALPix map balancing North and South distribution of rings to achieve the best performance on Harmonic Transforms Returns the grid object and the pixel indices array in RING ordering Parameters --------- nside : int HEALPix NSIDE parameter of the distributed map rank, n_mpi_processes, ints rank of the current MPI process and total number of processes Returns ------- grid : libsharp.healpix_grid libsharp object that includes metadata about HEALPix distributed rings local_pix : np.ndarray integer array of local pixel indices in the current MPI process in RING ordering """ if libsharp is None: raise RuntimeError('libsharp not available') autotimer = timing.auto_timer() nrings = 4 * nside - 1 # four missing pixels # ring indices are 1-based ring_indices_emisphere = np.arange(2 * nside, dtype=np.int32) + 1 local_ring_indices = ring_indices_emisphere[rank::n_mpi_processes] # to improve performance, symmetric rings north/south need to be in the same rank # therefore we use symmetry to create the full ring indexing if local_ring_indices[-1] == 2 * nside: # has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1]) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1]) grid = libsharp.healpix_grid(nside, rings=local_ring_indices) return grid, local_ring_indices
def test_basic(): lmax = 10 nside = 8 rank = MPI.COMM_WORLD.Get_rank() ms = np.arange(rank, lmax + 1, MPI.COMM_WORLD.Get_size(), dtype=np.int32) order = libsharp.packed_real_order(lmax, ms=ms) grid = libsharp.healpix_grid(nside) alm = np.zeros(order.local_size()) if rank == 0: alm[0] = 1 elif rank == 1: alm[0] = 1 map = libsharp.synthesis(grid, order, np.repeat(alm[None, None, :], 3, 0), comm=MPI.COMM_WORLD) assert np.all(map[2, :] == map[1, :]) and np.all(map[1, :] == map[0, :]) map = map[0, 0, :] print(rank, "shape", map.shape) print(rank, "mean", map.mean())
local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1] ) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1] ) print("rank", rank, "n_rings", len(local_ring_indices)) if not mpi: local_ring_indices = None grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(np.int64)) local_npix = grid.local_size() def expand_pix(startpix, ringpix, local_npix): """Turn first pixel index and number of pixel in full array of pixels to be optimized with cython or numba """ local_pix = np.empty(local_npix, dtype=np.int64) i = 0 for start, num in zip(startpix, ringpix): local_pix[i:i+num] = np.arange(start, start+num)
# therefore we use symmetry to create the full ring indexing if local_ring_indices[-1] == 2 * nside: # has equator ring local_ring_indices = np.concatenate( [local_ring_indices[:-1], nrings - local_ring_indices[::-1] + 1]) else: # does not have equator ring local_ring_indices = np.concatenate( [local_ring_indices, nrings - local_ring_indices[::-1] + 1]) print("rank", rank, "n_rings", len(local_ring_indices)) if not mpi: local_ring_indices = None grid = libsharp.healpix_grid(nside, rings=local_ring_indices) # returns start index of the ring and number of pixels startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(np.int64)) local_npix = grid.local_size() def expand_pix(startpix, ringpix, local_npix): """Turn first pixel index and number of pixel in full array of pixels to be optimized with cython or numba """ local_pix = np.empty(local_npix, dtype=np.int64) i = 0