Ejemplo n.º 1
0
def test_long_only():
    """ Far pair with no short-range contribution """
    pos = [(0.2, 0.2, 0.2), (0.7, 0.6, 0.5)]
    mass = [1, 10]
    print('Ewald summation of forces')
    acc = _direct_sum(pos, mass, ewald_corr=True)

    ewald = array([[0.00000000e+00, 5.26024612e+00, 7.09533177e+00],
                   [-6.66133815e-16, -5.26024612e-01, -7.09533177e-01]])
    max_acc = sqrt(square(ewald).sum(1).max())

    max_err = sqrt(square(ewald - acc).sum(1).max())
    print('Acceleration', repr(acc))
    assert (max_err < 1e-5)

    print('Total rate of change of momentum',
          (acc * reshape(mass, (len(mass), 1))).sum(0))
    fs = p3m.get_force_split(r_split=0.15, mode='erf')
    long_force = p3m.PMAccel(fs)
    accel = long_force.accel(mass, pos)
    print('Accel long', accel)
    accel_err = abs(accel - ewald).max() / max_acc

    print('Maximum relative error', accel_err)
    assert (accel_err < 2e-3)
Ejemplo n.º 2
0
def test_intermediate_grid():
    """ test an additional non-periodic grid """
    pts = [(0.5, 0.5, 0.5), (0.5, 0.8, 0.5), (0.55, 0.55, 0.55)]
    wts = [1, 2, 3]
    print('Ewald summation of forces')
    acc = _direct_sum(pts, wts, ewald_corr=True)

    print('Acceleration', repr(acc))
    r_coarse = 0.105
    print('Long-Short split of forces')

    fs = p3m.get_force_split(r_split=r_coarse,
                             mode='cubic')  #, kernel_pts=200)
    pairs, accel_short = p3m.pp_accel(fs, wts, pts,
                                      r_soft=None)  # Cubic-split Newtonian
    accel_long = p3m.PMAccel(fs).accel(wts, pts)
    accel = accel_short + accel_long
    print('Result', repr(accel))
    print('Long-Medium-Short split')
    ifs = p3m.IntermediateGrid(r_coarse=r_coarse,
                               ngrid=96,
                               centre=(0.5, 0.5, 0.5),
                               hw_min=0.01)
    print('Rlong', ifs.r_coarse, 'Rfine', ifs.r_fine, 'box width', ifs.hw * 2)
    idx_in, idx_in_nonghost, idx_out, idx_out_nonghost = ifs.split_in_vs_out(
        pts)
    print('idx in', idx_in, idx_in_nonghost)
    pos_in = array(pts)[idx_in]
    wts_in = array(wts)[idx_in]
    accel_int_pm = ifs.pm_accel(pos_in, wts_in, idx_in_nonghost)
    accel_int_pp = ifs.pp_accel(pos_in, wts_in, idx_in_nonghost)

    accel_int = accel_int_pm + accel_int_pp
    pos_out = array(pts)[idx_out]
    wts_out = array(wts)[idx_out]
    pairs, accel_short = p3m.pp_accel(fs, wts_out, pos_out,
                                      r_soft=None)  # Cubic-split Newtonian

    accel_short = accel_short[idx_out_nonghost]

    # add all the components
    accel = accel_long
    acs = zeros_like(accel)
    acs[idx_out[idx_out_nonghost]] += accel_short
    aci = zeros_like(accel)
    aci[idx_in[idx_in_nonghost]] += accel_int
    print('Accel int pp', accel_int_pp)
    print('Accel int', aci)
    print('Accel short', acs)
    print('ACCel long', accel_long)
    accel += aci + acs

    print('Result', repr(accel))

    err = abs(accel - acc)
    print('Error', err)
    assert (err.max() < 4.0)  # about 1.3 % error
Ejemplo n.º 3
0
def test_short_long():
    """ Combination of close (Newtonian) and far (periodic effects) pairs """
    from numpy import empty_like, arange
    print('A close pair and a far point')
    # worst-case scenario, short-pair near (0.1) splitting scale (0.105)
    pts = [(0.5, 0.5, 0.5), (0.5, 0.6, 0.5), (0.9, 0.3, 0.95)]
    wts = [1, 2, 3]
    print('Ewald summation of forces')
    acc = _direct_sum(pts, wts, ewald_corr=True)
    print('Short-long Acceleration', repr(acc))
    # Ewald (from direct sum)
    ewald = array([[2.04840161, 196.8858954, 1.18571601],
                   [1.63087151, -101.75612334, 0.92870922],
                   [-1.77004821, 2.20878376, -1.01437815]])

    max_acc = sqrt(square(ewald).sum(1).max())

    max_err = sqrt(square(ewald - acc).sum(1).max())

    assert (max_err < 1e-3)

    print('Total rate of change of momentum',
          (acc * reshape(wts, (len(wts), 1))).sum(0))
    print('Hash-grid summation of forces')
    fs = p3m.get_force_split(r_split=0.105, mode='erf')
    pairs, accel_short = p3m.pp_accel(fs, wts, pts,
                                      r_soft=None)  # Erf-split Newtonian

    assert (pairs == 1)  # Only the close pair

    print('Making long range force via fft')
    long_force = p3m.PMAccel(fs)

    accel_long = long_force.accel(wts, pts)

    accel = accel_short + accel_long
    print('short+long', accel)

    accel_err = abs(accel - ewald).max() / max_acc

    print('short+long maximum relative error', accel_err)
    assert (accel_err < 1.5e-2)
Ejemplo n.º 4
0
def test_inter_grid_halo():
    from numpy.random import RandomState

    rs = RandomState(seed=123)

    npts = 150
    phi = 2 * pi * rs.rand(npts)
    cos_theta = 2 * rs.rand(npts) - 1
    sin_theta = sqrt(1 - cos_theta**2)
    r = 0.5 * sqrt(
        (arange(npts) + 1.0) / npts
    )  # 1/r profile, like centre of NFW # mass is uniformly distributed over radii for isothermal halo (rho ~1/r^2)

    pos = empty((npts, 3))
    pos[:, 0] = 0.5 + r * sin_theta * cos(phi)
    pos[:, 1] = 0.5 + r * sin_theta * sin(phi)
    pos[:, 2] = 0.5 + r * cos_theta

    wts = ones(npts) * (1.0 / npts)
    print('Gravity via short-long')
    r_coarse = 0.15
    r_soft = 0.01
    print('Long-Short split of forces')

    fs = p3m.get_force_split(r_split=r_coarse,
                             mode='cubic')  #, kernel_pts=200)
    pairs, accel_short = p3m.pp_accel(fs, wts, pos, r_soft)
    accel_long = p3m.PMAccel(fs).accel(wts, pos)

    accel_LS = accel_short + accel_long
    print('Total pairs {:,}'.format(pairs))
    print('Gravity via short-med-long')
    ifs = p3m.IntermediateGrid(r_coarse=r_coarse,
                               ngrid=64,
                               centre=(0.5, 0.5, 0.5),
                               hw_min=r_coarse)
    print('Rlong', ifs.r_coarse, 'Rfine', ifs.r_fine, 'box width', ifs.hw * 2)
    idx_in, idx_in_nonghost, idx_out, idx_out_nonghost = ifs.split_in_vs_out(
        pos)
    print('Number of points in central region', len(idx_in_nonghost))

    print('Number of points outside is {:,}, including ghosts is {:,}'.format(
        len(idx_out_nonghost), len(idx_out)))

    accel_int_pm = ifs.pm_accel(pos[idx_in], wts[idx_in], idx_in_nonghost)
    accel_int_pp = ifs.pp_accel(pos[idx_in], wts[idx_in], idx_in_nonghost,
                                r_soft)

    accel_int = accel_int_pm + accel_int_pp
    pairs, accel_short = p3m.pp_accel(fs, wts[idx_out], pos[idx_out], r_soft)

    accel_short = accel_short[idx_out_nonghost]

    # add all the components
    accel_LMS = accel_long.copy()
    acs = zeros_like(accel_LMS)
    acs[idx_out[idx_out_nonghost]] += accel_short
    aci_pm = zeros_like(accel_LMS)
    aci_pm[idx_in[idx_in_nonghost]] += accel_int_pm
    aci_pp = zeros_like(accel_LMS)
    aci_pp[idx_in[idx_in_nonghost]] += accel_int_pp

    accel_LMS += aci_pm + aci_pp + acs

    print('RMS Long-short', rms(accel_LS))
    print('RMS Long-Med-Short', rms(accel_LMS))
    ix = arange(npts)  #idx_in[idx_in_nonghost]
    max_acc = sqrt(max(square(accel_LS).sum(1)))
    err = accel_LMS[ix] - accel_LS[ix]
    err2 = square(err).sum(1)
    idx_max = argmax(err2)
    rad_max = sqrt(square(pos[idx_max] - 0.5).sum())
    print('Position of maximum', pos[idx_max], 'radius', rad_max, 'AccelLS',
          accel_LS[idx_max], 'AccelLMS', accel_LMS[idx_max])
    print('M', aci_pm[idx_max], aci_pp[idx_max], 'L', accel_long[idx_max])
    print('Index of max', idx_max)
    max_error = sqrt(err2.max())

    print('Max error/max_acc', max_error / max_acc)
    assert (max_error < 0.01 * max_acc)
    print('RMS error/RMS acc', rms(err) / rms(accel_LS))
    assert (rms(err) < 0.01 * rms(accel_LS))
Ejemplo n.º 5
0
def test_cosmological_vels_agree_accel():
    """
    Linearity of cosmological accelerations.

    The cosmological ICs are made in the linear regime, and thus should have
    velocities proportional to the gravitational acceleration. By making a 
    realisation and using PPPM when can calculate the gravity and confirm this.
    """

    redshift = 50
    # Small box dominated by longest modes
    boxsize = 10.0  # Mpc/h
    H0 = 70.0  # km / s / Mpc
    a = 1.0 / (1.0 + redshift)
    omegaM = 0.279
    omegaL = 0.721
    sigma8 = 0.8

    pspec = pspec_normalised_by_sigma8_expansion(efstathiou,
                                                 sigma8=sigma8,
                                                 a=a,
                                                 omegaM=omegaM,
                                                 omegaL=omegaL)

    ngrid = 30

    disp_grid = build_displacement(boxsize=boxsize,
                                   ngrid=ngrid,
                                   power_func=pspec)
    disp_sampler = displacement_sampler_factory(disp_grid, boxsize)

    # fill a box with uniform points
    xyz = (mgrid[:ngrid, :ngrid, :ngrid] + 0.5) * (boxsize / ngrid)

    uni_pts = reshape(xyz, (3, ngrid**3)).T
    uni_sizes = ones(ngrid**3) * (boxsize / ngrid)

    dm_pos, dm_mass, dm_vel, dm_nums = mass_field(boxsize, uni_pts, uni_sizes,
                                                  disp_sampler, a, omegaM,
                                                  omegaL, H0)

    print('DM vel shape', dm_vel.shape, dm_mass.shape, dm_pos.shape, 'mass',
          dm_mass)
    rms_vel = sqrt(square(dm_vel).sum(1).mean(dtype=float64))
    print('RMS velocity for DM', rms_vel)

    # now do gravity
    rcrit = 2.0 / ngrid

    log = VerboseTimingLog(insert_timings=True)
    fs = p3m.get_force_split(rcrit, mode='erf')
    pos = dm_pos * (1.0 / boxsize)

    wts = empty(pos.shape[0])

    h = H0 / 100.0
    wts[:] = dm_mass * G * (msun / h) / (boxsize * mpc / h)**3
    print('Pos in', pos.min(axis=0), pos.max(axis=0))
    pairs, acc_short = p3m.pp_accel(fs, wts, pos,
                                    r_soft=None)  # Erf-split Newtonian
    long_force = p3m.PMAccel(fs)
    acc_long = long_force.accel(wts, pos)
    log.close()
    acc = (acc_short + acc_long) / (a * a * a)  # d^2 x / dt^2

    hubble = hubble_closure(H0 * (1e5 / mpc), omegaM, omegaL)

    # In linear regime of matter-dominated universe, vel = 2/3 H * acc
    eds_vel = acc * (boxsize * mpc /
                     h) * 1e-5 / hubble(a) * a * 2.0 / 3.0  # in km/s physical

    dm_vel *= sqrt(a)  # convert Gadget vels to km/s
    print('Samples:')
    print(eds_vel[10], 'km/s velocity (EdS approx from accel)')
    print(dm_vel[10], 'km/s velocity from linear theory')
    err = rms(dm_vel - eds_vel) / rms(dm_vel)
    print('Error in', err.min(), err.max(), 'mean', err.mean())
    assert (err.mean() < 0.06)