|
7 | 7 | from nbodykit.meshtools import SlabIterator |
8 | 8 | from nbodykit.base.catalog import CatalogSourceBase |
9 | 9 | from nbodykit.base.mesh import MeshSource |
| 10 | +from mpi4py import MPI |
10 | 11 |
|
11 | 12 | class FFTBase(object): |
12 | 13 | """ |
@@ -143,7 +144,7 @@ def _compute_3d_power(self, first, second): |
143 | 144 |
|
144 | 145 |
|
145 | 146 | class FFTPower(FFTBase): |
146 | | - """ |
| 147 | + r""" |
147 | 148 | Algorithm to compute the 1d or 2d power spectrum and/or multipoles |
148 | 149 | in a periodic box, using a Fast Fourier Transform (FFT). |
149 | 150 |
|
@@ -227,10 +228,10 @@ def __init__(self, first, mode, Nmesh=None, BoxSize=None, second=None, |
227 | 228 | self.attrs.update(self.power.attrs) |
228 | 229 |
|
229 | 230 | def run(self): |
230 | | - """ |
| 231 | + r""" |
231 | 232 | Compute the power spectrum in a periodic box, using FFTs. |
232 | 233 |
|
233 | | - Returns |
| 234 | + Returns |
234 | 235 | ------- |
235 | 236 | power : :class:`~nbodykit.binned_statistic.BinnedStatistic` |
236 | 237 | a BinnedStatistic object that holds the measured :math:`P(k)` or |
@@ -735,24 +736,27 @@ def _find_unique_edges(x, x0, xmax, comm): |
735 | 736 |
|
736 | 737 | Returns edges and the true centers |
737 | 738 | """ |
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 |
742 | 742 |
|
| 743 | + def find_unique_local(fx2, binning): |
| 744 | + """Find unique values in a floating point array by making integer bins""" |
743 | 745 | fx2 = numpy.ravel(fx2) |
744 | | - ix2 = numpy.int64(fx2 / (x0.min() * 0.5) ** 2 + 0.5) |
| 746 | + ix2 = numpy.int64(fx2 / binning + 0.5) |
745 | 747 | ix2, ind = numpy.unique(ix2, return_index=True) |
746 | 748 | fx2 = fx2[ind] |
747 | | - return fx2 ** 0.5 |
| 749 | + return fx2 |
748 | 750 |
|
749 | | - fx = find_unique_local(x, x0) |
| 751 | + binning = (x0.min() * 0.05)**2 |
| 752 | + fx = find_unique_local(fx2, binning)**0.5 |
750 | 753 |
|
751 | 754 | fx = fx[fx < xmax] |
752 | 755 | 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) |
756 | 760 |
|
757 | 761 | # now make some reasonable bins. |
758 | 762 | width = numpy.diff(fx) |
|
0 commit comments