def whitenoise_to_linear(nc,
                         boxsize,
                         whitec,
                         pk,
                         kvec=None,
                         batch_size=1,
                         seed=None,
                         dtype=tf.float32,
                         name="LinearField"):
  """Generates a linear field with a given linear power spectrum and whitenoise realization
  """
  with tf.name_scope(name):
    # Transform nc to a list of necessary
    if isinstance(nc, int):
      nc = [nc, nc, nc]
    if isinstance(boxsize, int) or isinstance(boxsize, float):
      boxsize = [boxsize, boxsize, boxsize]

    if kvec is None:
      kvec = fftk(nc, symmetric=False)
    kmesh = sum((kk / boxsize[i] * nc[i])**2 for i, kk in enumerate(kvec))**0.5
    pkmesh = pk(kmesh)

    lineark = tf.multiply(whitec, (pkmesh /
                                   (boxsize[0] * boxsize[1] * boxsize[2]))**0.5)
    linear = c2r3d(lineark, norm=nc[0] * nc[1] * nc[2], name=name, dtype=dtype)
    return linear
Esempio n. 2
0
def lpt1(dlin_k, pos, kvec=None, name="LTP1"):
    """ Run first order LPT on linear density field, returns displacements of particles
      reading out at q. The result has the same dtype as q.

  Parameters:
  -----------
  dlin_k: TODO: @modichirag add documentation

  Returns:
  --------
  displacement: tensor (batch_size, npart, 3)
    Displacement field
  """
    with tf.name_scope(name):
        dlin_k = tf.convert_to_tensor(dlin_k, name="lineark")
        pos = tf.convert_to_tensor(pos, name="pos")

        shape = dlin_k.get_shape()
        batch_size, nc = shape[0], shape[1:]
        if kvec is None:
            kvec = fftk(nc, symmetric=False)

        lap = tf.cast(laplace_kernel(kvec), tf.complex64)

        displacement = []
        for d in range(3):
            kweight = gradient_kernel(kvec, d) * lap
            dispc = tf.multiply(dlin_k, kweight)
            disp = c2r3d(dispc, norm=nc[0] * nc[1] * nc[2])
            displacement.append(cic_readout(disp, pos))
        displacement = tf.stack(displacement, axis=2)
        return displacement
def linear_field(nc,
                 boxsize,
                 pk,
                 kvec=None,
                 batch_size=1,
                 seed=None,
                 dtype=tf.float32,
                 name="LinearField"):
    """Generates a linear field with a given linear power spectrum.
  
  Parameters:
  -----------
  nc: int, or list of ints
    Number of cells in the field. If a list is provided, number of cells per
    dimension.
  boxsize: float, or list of floats
    Physical size of the cube, in Mpc/h.
  pk: interpolator
    Power spectrum to use for the field
  kvec: array
    k_vector corresponding to the cube, optional
  batch_size: int
    Size of batches
  seed: int
    Seed to initialize the gaussian random field
  dtype: tf.dtype
    Type of the sampled field, e.g. tf.float32 or tf.float64
  Returns
  ------
  linfield: tensor (batch_size, nc, nc, nc)
    Realization of the linear field with requested power spectrum
  """
    with tf.name_scope(name):
        # Transform nc to a list of necessary
        if isinstance(nc, int):
            nc = [nc, nc, nc]
        if isinstance(boxsize, int) or isinstance(boxsize, float):
            boxsize = [boxsize, boxsize, boxsize]

        if kvec is None:
            kvec = fftk(nc, symmetric=False)
        kmesh = sum(
            (kk / boxsize[i] * nc[i])**2 for i, kk in enumerate(kvec))**0.5
        pkmesh = pk(kmesh)

        whitec = white_noise(nc,
                             batch_size=batch_size,
                             seed=seed,
                             type='complex')
        lineark = tf.multiply(
            whitec, (pkmesh / (boxsize[0] * boxsize[1] * boxsize[2]))**0.5)
        linear = c2r3d(lineark,
                       norm=nc[0] * nc[1] * nc[2],
                       name=name,
                       dtype=dtype)
        return linear
Esempio n. 4
0
def lpt2_source(dlin_k, kvec=None, name="LPT2Source"):
    """ Generate the second order LPT source term.

  Parameters:
  -----------
  dlin_k: TODO: @modichirag add documentation

  Returns:
  --------
  source: tensor (batch_size, nc, nc, nc)
    Source term
  """
    with tf.name_scope(name):
        dlin_k = tf.convert_to_tensor(dlin_k, name="lineark")

        shape = dlin_k.get_shape()
        batch_size, nc = shape[0], shape[1:]
        if kvec is None:
            kvec = fftk(nc, symmetric=False)
        source = tf.zeros(tf.shape(dlin_k))
        D1 = [1, 2, 0]
        D2 = [2, 0, 1]

        phi_ii = []
        # diagnoal terms
        lap = tf.cast(laplace_kernel(kvec), tf.complex64)

        for d in range(3):
            grad = gradient_kernel(kvec, d)
            kweight = lap * grad * grad
            phic = tf.multiply(dlin_k, kweight)
            phi_ii.append(c2r3d(phic, norm=nc[0] * nc[1] * nc[2]))

        for d in range(3):
            source = tf.add(source, tf.multiply(phi_ii[D1[d]], phi_ii[D2[d]]))

        # free memory
        phi_ii = []

        # off-diag terms
        for d in range(3):
            gradi = gradient_kernel(kvec, D1[d])
            gradj = gradient_kernel(kvec, D2[d])
            kweight = lap * gradi * gradj
            phic = tf.multiply(dlin_k, kweight)
            phi = c2r3d(phic, norm=nc[0] * nc[1] * nc[2])
            source = tf.subtract(source, tf.multiply(phi, phi))

        source = tf.multiply(source, 3.0 / 7.)
        return r2c3d(source, norm=nc[0] * nc[1] * nc[2])
def apply_pgd(x, delta_k, alpha, kl, ks, kvec=None, name="ApplyPGD"):
    """
  Estimate the short range force on the particles given a state.

  Parameters:
  -----------
  x: tensor
    Input state tensor of shape (3, batch_size, npart, 3) 
    
  delta_k:
     Density in the Fourier space   
    
  alpha: float
    Free parameter. Factor of proportionality between the displacement and the Particle-mesh force.

  kl: float
    Long range scale parameter
    
  ks: float
    Short range scale parameter
  """
    with tf.name_scope(name):
        x = tf.convert_to_tensor(x, name="pos")
        delta_k = tf.convert_to_tensor(delta_k, name="delta_k")

        shape = delta_k.get_shape()
        nc = shape[1:]

        if kvec is None:
            kvec = fftk(nc, symmetric=False)

        ndim = 3
        norm = nc[0] * nc[1] * nc[2]

        lap = tf.cast(laplace_kernel(kvec), tf.complex64)
        PGD_range = tf.cast(PGD_kernel(kvec, kl, ks), tf.complex64)
        kweight = lap * PGD_range
        pot_k = tf.multiply(delta_k, kweight)

        f = []
        for d in range(ndim):
            force_dc = tf.multiply(pot_k, gradient_kernel(kvec, d))
            forced = c2r3d(force_dc, norm=norm)
            force = cic_readout(forced, x)
            f.append(force)

        f = tf.stack(f, axis=2)
        f = tf.multiply(f, alpha)
        return f
def compensate_cic(field, name="CompensateCiC"):
    """
  Compensate for CiC painting

  Args:
    field: input 3D cic-painted field

  Returns:
    compensated_field
  """
    with tf.name_scope(name):
        shape = field.get_shape()
        batch_size, nc = shape[0], shape[1:]

        kvec = fpk.fftk(nc, symmetric=False)

        delta_k = r2c3d(field, norm=nc[0] * nc[1] * nc[2])
        delta_k = tf.cast(fpk.cic_compensation(kvec), tf.complex64) * delta_k
        return c2r3d(delta_k, norm=nc[0] * nc[1] * nc[2])
Esempio n. 7
0
def apply_longrange(x,
                    delta_k,
                    split=0,
                    factor=1,
                    kvec=None,
                    name="ApplyLongrange"):
    """ like long range, but x is a list of positions
  TODO: Better documentation, also better name?
  """
    # use the four point kernel to suppresse artificial growth of noise like terms
    with tf.name_scope(name):
        x = tf.convert_to_tensor(x, name="pos")
        delta_k = tf.convert_to_tensor(delta_k, name="delta_k")

        shape = delta_k.get_shape()
        nc = shape[1:]

        if kvec is None:
            kvec = fftk(nc, symmetric=False)

        ndim = 3
        norm = nc[0] * nc[1] * nc[2]
        lap = tf.cast(laplace_kernel(kvec), tf.complex64)
        fknlrange = longrange_kernel(kvec, split)
        kweight = lap * fknlrange
        pot_k = tf.multiply(delta_k, kweight)

        f = []
        for d in range(ndim):
            force_dc = tf.multiply(pot_k, gradient_kernel(kvec, d))
            forced = c2r3d(force_dc, norm=norm)
            force = cic_readout(forced, x)
            f.append(force)

        f = tf.stack(f, axis=2)
        f = tf.multiply(f, factor)
        return f