Skip to content

Commit fc32c39

Browse files
committed
add almxfl test
1 parent 158323a commit fc32c39

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# This test needs to be run with:
2+
3+
# mpirun -np X python test_smoothing_noise_pol_mpi.py
4+
5+
from mpi4py import MPI
6+
7+
import numpy as np
8+
9+
import healpy as hp
10+
11+
import libsharp
12+
13+
mpi = True
14+
rank = MPI.COMM_WORLD.Get_rank()
15+
16+
nside = 256
17+
npix = hp.nside2npix(nside)
18+
19+
np.random.seed(100)
20+
input_map = np.random.normal(size=(3, npix))
21+
fwhm_deg = 10
22+
lmax = 512
23+
24+
nrings = 4 * nside - 1 # four missing pixels
25+
26+
if rank == 0:
27+
print("total rings", nrings)
28+
29+
n_mpi_processes = MPI.COMM_WORLD.Get_size()
30+
rings_per_process = nrings // n_mpi_processes + 1
31+
# ring indices are 1-based
32+
33+
ring_indices_emisphere = np.arange(2*nside, dtype=np.int32) + 1
34+
local_ring_indices = ring_indices_emisphere[rank::n_mpi_processes]
35+
36+
# to improve performance, simmetric rings north/south need to be in the same rank
37+
# therefore we use symmetry to create the full ring indexing
38+
39+
if local_ring_indices[-1] == 2 * nside:
40+
# has equator ring
41+
local_ring_indices = np.concatenate(
42+
[local_ring_indices[:-1],
43+
nrings - local_ring_indices[::-1] + 1]
44+
)
45+
else:
46+
# does not have equator ring
47+
local_ring_indices = np.concatenate(
48+
[local_ring_indices,
49+
nrings - local_ring_indices[::-1] + 1]
50+
)
51+
52+
print("rank", rank, "n_rings", len(local_ring_indices))
53+
54+
if not mpi:
55+
local_ring_indices = None
56+
grid = libsharp.healpix_grid(nside, rings=local_ring_indices)
57+
58+
# returns start index of the ring and number of pixels
59+
startpix, ringpix, _, _, _ = hp.ringinfo(nside, local_ring_indices.astype(np.int64))
60+
61+
local_npix = grid.local_size()
62+
63+
def expand_pix(startpix, ringpix, local_npix):
64+
"""Turn first pixel index and number of pixel in full array of pixels
65+
66+
to be optimized with cython or numba
67+
"""
68+
local_pix = np.empty(local_npix, dtype=np.int64)
69+
i = 0
70+
for start, num in zip(startpix, ringpix):
71+
local_pix[i:i+num] = np.arange(start, start+num)
72+
i += num
73+
return local_pix
74+
75+
local_pix = expand_pix(startpix, ringpix, local_npix)
76+
77+
local_map = input_map[:, local_pix]
78+
79+
local_hitmap = np.zeros(npix)
80+
local_hitmap[local_pix] = 1
81+
hp.write_map("hitmap_{}.fits".format(rank), local_hitmap, overwrite=True)
82+
83+
print("rank", rank, "npix", npix, "local_npix", local_npix, "local_map len", len(local_map), "unique pix", len(np.unique(local_pix)))
84+
85+
local_m_indices = np.arange(rank, lmax + 1, MPI.COMM_WORLD.Get_size(), dtype=np.int32)
86+
if not mpi:
87+
local_m_indices = None
88+
89+
order = libsharp.packed_real_order(lmax, ms=local_m_indices)
90+
local_nl = order.local_size()
91+
print("rank", rank, "local_nl", local_nl, "mval", order.mval())
92+
93+
mpi_comm = MPI.COMM_WORLD if mpi else None
94+
95+
# map2alm
96+
# maps in libsharp are 3D, 2nd dimension is IQU, 3rd is pixel
97+
98+
alm_sharp_I = libsharp.analysis(grid, order,
99+
np.ascontiguousarray(local_map[0].reshape((1, 1, -1))),
100+
spin=0, comm=mpi_comm)
101+
alm_sharp_P = libsharp.analysis(grid, order,
102+
np.ascontiguousarray(local_map[1:].reshape((1, 2, -1))),
103+
spin=2, comm=mpi_comm)
104+
105+
beam = hp.gauss_beam(fwhm=np.radians(fwhm_deg), lmax=lmax, pol=True)
106+
107+
print("Smooth")
108+
# smooth in place (zonca implemented this function)
109+
order.almxfl(alm_sharp_I, np.ascontiguousarray(beam[:, 0:1]))
110+
order.almxfl(alm_sharp_P, np.ascontiguousarray(beam[:, (1, 2)]))
111+
112+
# alm2map
113+
114+
new_local_map_I = libsharp.synthesis(grid, order, alm_sharp_I, spin=0, comm=mpi_comm)
115+
new_local_map_P = libsharp.synthesis(grid, order, alm_sharp_P, spin=2, comm=mpi_comm)
116+
117+
# Transfer map to first process for writing
118+
119+
local_full_map = np.zeros(input_map.shape, dtype=np.float64)
120+
local_full_map[0, local_pix] = new_local_map_I
121+
local_full_map[1:, local_pix] = new_local_map_P
122+
123+
output_map = np.zeros(input_map.shape, dtype=np.float64) if rank == 0 else None
124+
mpi_comm.Reduce(local_full_map, output_map, root=0, op=MPI.SUM)
125+
126+
if rank == 0:
127+
# hp.write_map("sharp_smoothed_map.fits", output_map, overwrite=True)
128+
# hp_smoothed = hp.alm2map(hp.map2alm(input_map, lmax=lmax), nside=nside) # transform only
129+
hp_smoothed = hp.smoothing(input_map, fwhm=np.radians(fwhm_deg), lmax=lmax)
130+
std_diff = (hp_smoothed-output_map).std()
131+
print("Std of difference between libsharp and healpy", std_diff)
132+
# hp.write_map(
133+
# "healpy_smoothed_map.fits",
134+
# hp_smoothed,
135+
# overwrite=True
136+
# )
137+
assert std_diff < 1e-5

0 commit comments

Comments
 (0)