Skip to content

Commit f89c1f3

Browse files
committed
Fix auto-binning the power spectrum with dk=0
Previous code used numpy.unique with a floating point value to remove duplicate bins from different ranks. This led to several zero-width bins and thus NaNs in the averaged k values. Replace this by using the proper integerised duplicate value finder already in the code for local de-duplication after gathering from all ranks. I'm not sure how this worked before.
1 parent 9eceb60 commit f89c1f3

1 file changed

Lines changed: 17 additions & 13 deletions

File tree

‎nbodykit/algorithms/fftpower.py‎

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from nbodykit.meshtools import SlabIterator
88
from nbodykit.base.catalog import CatalogSourceBase
99
from nbodykit.base.mesh import MeshSource
10+
from mpi4py import MPI
1011

1112
class FFTBase(object):
1213
"""
@@ -143,7 +144,7 @@ def _compute_3d_power(self, first, second):
143144

144145

145146
class FFTPower(FFTBase):
146-
"""
147+
r"""
147148
Algorithm to compute the 1d or 2d power spectrum and/or multipoles
148149
in a periodic box, using a Fast Fourier Transform (FFT).
149150
@@ -227,10 +228,10 @@ def __init__(self, first, mode, Nmesh=None, BoxSize=None, second=None,
227228
self.attrs.update(self.power.attrs)
228229

229230
def run(self):
230-
"""
231+
r"""
231232
Compute the power spectrum in a periodic box, using FFTs.
232233
233-
Returns
234+
Returns
234235
-------
235236
power : :class:`~nbodykit.binned_statistic.BinnedStatistic`
236237
a BinnedStatistic object that holds the measured :math:`P(k)` or
@@ -735,24 +736,27 @@ def _find_unique_edges(x, x0, xmax, comm):
735736
736737
Returns edges and the true centers
737738
"""
738-
def find_unique_local(x, x0):
739-
fx2 = 0
740-
for xi, x0i in zip(x, x0):
741-
fx2 = fx2 + xi ** 2
739+
fx2 = 0
740+
for xi in x:
741+
fx2 = fx2 + xi ** 2
742742

743+
def find_unique_local(fx2, binning):
744+
"""Find unique values in a floating point array by making integer bins"""
743745
fx2 = numpy.ravel(fx2)
744-
ix2 = numpy.int64(fx2 / (x0.min() * 0.5) ** 2 + 0.5)
746+
ix2 = numpy.int64(fx2 / binning + 0.5)
745747
ix2, ind = numpy.unique(ix2, return_index=True)
746748
fx2 = fx2[ind]
747-
return fx2 ** 0.5
749+
return fx2
748750

749-
fx = find_unique_local(x, x0)
751+
binning = (x0.min() * 0.05)**2
752+
fx = find_unique_local(fx2, binning)**0.5
750753

751754
fx = fx[fx < xmax]
752755
fx = numpy.concatenate(comm.allgather(fx), axis=0)
753-
# may have duplicates after allgather
754-
fx = numpy.unique(fx)
755-
fx.sort()
756+
# May have duplicates after allgather: need to re-bin.
757+
# We want to be picky about duplicates, so use a small bin size
758+
minx0 = comm.allreduce(x0.min(), op=MPI.MIN)
759+
fx = find_unique_local(fx, minx0 * 1e-5)
756760

757761
# now make some reasonable bins.
758762
width = numpy.diff(fx)

0 commit comments

Comments
 (0)