Beispiel #1
0
def init_pos(natom):
    from qharv.inspect import crystal
    from ase import Atoms
    from ase.build import make_supercell
    rho = 2.2e22 * 1e6 / 1e30  # atoms/A^3
    lbox = (natom / rho)**(1. / 3)
    nxf = (natom / 4.)**(1. / 3)
    nx = int(round(nxf))
    if not np.isclose(nx, nxf):
        raise RuntimeError('natom=%d nxf=%3.2f!=%d' % (natom, nxf, nx))
    # create FCC crystal
    alat = lbox / nx
    axes0 = alat / 2 * (np.ones(3) - np.eye(3))
    tmat = nx * (np.ones(3) - 2 * np.eye(3))
    s0 = Atoms('H', cell=axes0, positions=[[0, 0, 0]], pbc=[1, 1, 1])
    s1 = make_supercell(s0, tmat)
    pos = s1.get_positions()
    axes = s1.get_cell()
    # check density
    rho1 = natom / axes_pos.volume(axes)
    if not np.isclose(rho, rho1):
        raise RuntimeError('supercell density is wrong')
    # save/view crystal
    fig, ax = volumetric.figax3d()
    crystal.draw_cell(ax, axes)
    crystal.draw_atoms(ax, pos)
    plt.show()
    return pos
Beispiel #2
0
def rpa_dt(axes, rs, nx=32):
    """ calculate kinetic finite size error assuming RPA U(k) and S(k)

  Args:
    raxes (np.array): reciprocal space lattice
    rs (float): Wigner-Seitz radius i.e. density parameter
  Return:
    float: kinetic finite size correction
  """
    from qharv.inspect import axes_pos

    density = (4 * np.pi / 3 * rs**3.)**(-1)

    # get RPA U(k) and S(k)
    kf = heg_kfermi(rs)

    fuk = lambda k: gaskell_rpa_uk(k, rs, kf)
    fsk = effective_fsk_from_fuk(fuk, rs)

    # setup integration grid
    raxes = axes_pos.raxes(axes)
    qgrid = mp_grid(raxes, nx)

    # perform quadrature
    #  weights
    rvol = axes_pos.volume(raxes)
    intnorm = 1. / (2 * np.pi)**3 * rvol / nx**3 * density
    #  sum
    qmags = np.linalg.norm(qgrid, axis=1)
    integrand = lambda k: 0.5 * k**2 * fuk(k)**2 * fsk(k)
    dtlr = intnorm * integrand(qmags).sum()
    return dtlr
Beispiel #3
0
def gofr_snapshot(axes, pos, rmax, rmin=0, nbin=40, gofr_norm=None):
    """ calculate the pair correlation function of a snapshot of a crystal structure given the 'axes' of the simulation cell and the positions ('pos') of atoms inside the cell.
    'rmax' is the maximum pair distance to histogram. 'rmin','rmax', and 'nbin' are passed to numpy.histogram to generate the results.
    return 3 lists: r, g(r), and g(r) normalization.
    Note: if a gofr_norm is given, then it will not be recalculated. This can save time if the simulation box does not change.
    Args: 
      axes (np.array): crystal lattice vectors.
      pos (np.array):  positions of atoms. 
      rmax (float): maximum distance to calculate g(r) to.
      rmin (float,optional): minimum distance to calculate g(r) to, default is 0.
      nbin (int,optional): number of bins, default is 40.
      gofr_norm (float,optional): normalization factor for g(r), default is to recalculate.
    Returns:
      (np.array,np.array,float): (r,g(r),normalization) """
    from ase.geometry import get_distances
    from qharv.inspect.axes_pos import volume
    cell_volume = volume(axes)
    nptcl = len(pos)
    dtable = get_distances(pos, cell=axes, pbc=True)[1]

    # upper triagular distance matrix (i.e. unique pair distances)
    i_triu = np.triu_indices(nptcl, m=nptcl, k=1)
    pair_dists = dtable[i_triu]

    counts, ticks = np.histogram(pair_dists, range=(rmin, rmax), bins=nbin)
    myx = (ticks[:-1] + ticks[1:]) / 2.
    dx = myx[1] - myx[0]

    if gofr_norm is None:
        # gofr_norm = 4*np.pi*myx**2.*dx * nptcl*(nptcl-1)/2./struct.volume
        gofr_norm = 4 * np.pi * myx**2. * dx * nptcl**2. / cell_volume / 2.
    # end if
    myy = counts / gofr_norm

    return myx, myy, gofr_norm
Beispiel #4
0
def get_density(doc):
    from qharv.inspect import axes_pos
    entry = get_axes_pos(doc)
    volume = axes_pos.volume(entry['axes'])
    natom = len(entry['pos'])
    rho = natom / volume
    rs = (3. / (4 * np.pi * rho))**(1. / 3)
    return {'rs': rs, 'volume': volume, 'rho': rho}
Beispiel #5
0
def evaluate_ksum1d(fy1d, raxes, kcut, kmax, dk):
    from qharv.inspect import axes_pos
    rvol = axes_pos.volume(raxes)
    kmags = np.arange(kcut, kmax, dk)
    sumnorm = (4 * np.pi * kmags**2 * dk) * rvol / (2 * np.pi)**3
    yvals = fy1d(kmags) * sumnorm
    sumval = np.sum(yvals)
    return sumval
Beispiel #6
0
def get_qvecs_and_intnorm(axes, mx):
  from qharv.inspect import axes_pos
  # get qvectors
  raxes = axes_pos.raxes(axes)
  fvecs = 1./mx*axes_pos.cubic_pos(mx)
  qvecs = np.dot(fvecs, raxes)
  qvecs -= qvecs.mean(axis=0)
  # calculate integration norm
  intnorm = axes_pos.volume(raxes)/mx**3/(2*np.pi)**3
  return qvecs, intnorm
Beispiel #7
0
    def evaluate_fsc_sum(self,
                         fnk,
                         kvecs,
                         raxes,
                         kmax,
                         nsh=4,
                         nbig=4,
                         show_progress=True,
                         extrap=True,
                         alpha=None):
        nk, ndim = kvecs.shape

        def fnk1(kvecs):
            kmags = np.linalg.norm(kvecs, axis=-1)
            return fnk(kmags)

        dnk = []
        if extrap:
            from qharv.sieve.scalar_df import poly_extrap_to_x0
            from qharv.inspect import axes_pos
            vol0 = (2 * np.pi)**3 / axes_pos.volume(raxes)
            vol1 = vol0 * nbig**3
        if show_progress:
            from progressbar import ProgressBar
            bar = ProgressBar(maxval=nk)
        for ik, kvec in enumerate(kvecs):

            def dnk1(qvecs):
                qmags = np.linalg.norm(qvecs, axis=-1)
                dnkval = fnk1(qvecs+kvec[np.newaxis, :]) -\
                         fnk1(kvec[np.newaxis, :])
                delta = self.delta(qmags)
                return delta * dnkval

            # do sum in small cell
            nk0 = evaluate_ksum(dnk1, raxes, kmax, nsh)
            # redo sum in big cell
            nk1 = evaluate_ksum(dnk1, raxes / nbig, kmax, nsh * nbig)
            if extrap:
                if alpha is None:
                    if ndim == 3:
                        alpha = -1. / 3
                    elif ndim == 2:
                        alpha = -1. / 4
                    else:
                        raise RuntimeError('unknown dimension %d' % ndim)
                myx = [vol0**alpha, vol1**alpha]
                myym = [nk0, nk1]
                myye = [1e-6, 1e-6]
                dnk1, dnk1e = poly_extrap_to_x0(myx, myym, myye, 1)
            else:
                dnk1 = nk1 - nk0
            dnk.append(dnk1)
            bar.update(ik)
        return np.array(dnk)
Beispiel #8
0
def evaluate_ksum(fy, raxes, kmax, nsh):
    from qharv.inspect import axes_pos
    rvol = axes_pos.volume(raxes)
    sumnorm = rvol / (2 * np.pi)**3
    # get kvectors within cutoff
    kvecs = get_kshells(nsh, raxes)
    kmags = np.linalg.norm(kvecs, axis=-1)
    sel = (1e-4 < kmags) & (kmags < kmax)
    kvecs = kvecs[sel]
    kmags = kmags[sel]
    # evaluate function on kvectors
    yvals = fy(kvecs)
    sumval = sumnorm * np.sum(yvals)
    return sumval
Beispiel #9
0
 def init_missing_qvecs(self, raxes, mx):
     """Assume cubic cell, get integration grid within missing volume"""
     ## cubic box
     #dqx = blat/mx
     #qvecs = dqx*cubic_pos(mx)
     #self._intnorm = dqx**3/(2*np.pi)**3
     # non-cubic box
     from qharv.inspect.axes_pos import volume
     fvecs = 1. / mx * cubic_pos(mx)
     qvecs = np.dot(fvecs, raxes)
     qvecs -= qvecs.mean(axis=0)
     self._intnorm = volume(raxes) / mx**3 / (2 * np.pi)**3
     self._qvecs = qvecs
     self._init_fsc = True
     return qvecs