示例#1
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
示例#2
0
def heg_jas(rs, axes, nr, nsh0=5, kc=None, zoom=1e10):
    # note zoom of 1e10 keeps 10 digits when grouping kshells
    #  probably too high of a resolution, but this is QMCPACK default
    kf = heg_kfermi(rs)  # assume unpolarized
    if kc is None:
        kc = kf
    from qharv.inspect import axes_pos
    rcut = axes_pos.rwsc(axes)
    # step 1: build short-range Jastrow
    uuc, udc = get_rpa_coeff(rs, rcut, nr)
    j2sr = fusr(rcut, uuc, udc)
    # step 2: find unique kmags
    raxes = axes_pos.raxes(axes)
    kvecs = get_kshells(nsh0, raxes)
    kmags = np.linalg.norm(kvecs, axis=-1)
    sel = (0 < kmags) & (kmags < kc)
    import static_correlation as sc
    #ukmags = np.unique(kmags[sel])  # no tolerance option
    kmags1 = kmags[sel]
    sels = sc.kshell_sels(kmags1, zoom)
    ukmags = np.array([kmags1[s].mean() for s in sels])
    # step 3: get Ulr
    urpa = gaskell_rpa_uk(ukmags, rs, kf)
    usrk = evaluate_ft(ukmags, j2sr, rcut)
    ulrk = usrk - urpa
    return ukmags, ulrk, uuc, udc
示例#3
0
def sofk_snapshot(axes, pos, nkmax=5, legal_kvecs=None):
    """ calculate the structure factor of a snapshot of a crystal structure given 'axes' and 'pos' of atoms.
    'nkmax' is the number of kvectors to include in each of x,y,z directions. 
    return 2 lists: legal kvectors, and S(k) of each kvector 
    Args: 
      axes (np.array): crystal lattice vectors.
      pos (np.array):  positions of atoms. 
      nkmax (int,optional): maximum number of kvectors in each spatial dimension, default is 5. Used only if legal_kvecs is not give.
      leagal_kvecs (np.array,optional): kvectors upon which S(k) is defined, default is to recalculate up to nkmax.
    Returns:
      (np.array,np.array): (kvecs,S(k))
    """
    from qharv.inspect.axes_pos import raxes

    rho = lambda kvec: np.exp(1j * np.dot(pos, kvec)).sum()
    reclat = raxes(axes)

    if legal_kvecs is None:
        import chiesa_correction as chc
        cube_pts = chc.cubic_pos(nkmax)
        legal_kvecs = np.dot(cube_pts[1:], reclat)

    sk_arr = np.array([(rho(kvec) * rho(-kvec)).real / len(pos)
                       for kvec in legal_kvecs])

    return legal_kvecs, sk_arr
示例#4
0
def detect_p21c_layers(mols, kfracs=None):
  from qharv.inspect import axes_pos
  # setup S(k) calculation
  from qharv_db import grsk
  if kfracs is None:
    kfracs = np.array([
      [0, -8, 16],
      [0,  8, 16],
    ])
  axes = mols.get_cell()
  raxes = axes_pos.raxes(axes)
  kvecs = np.dot(kfracs, raxes)

  # detect layers
  layers = find_layers(mols)
  groups = extract_layers(layers, [mols])
  grps = [g[0] for g in groups]

  # loop through 3 layers at a time
  nlayer = len(grps)
  layer_desc = []
  for ilayer in range(1, nlayer-1):
    pos0 = grps[ilayer-1]
    pos1 = grps[ilayer]
    pos2 = grps[ilayer+1]
    pos = np.concatenate([pos0, pos1, pos2], axis=0)
    sk1 = grsk.Sk(kvecs, pos)
    layer_desc.append(sk1.sum())
  return layer_desc
示例#5
0
def get_all_rhok(fwf, kbrags, norb=None, ispin=0, show_progress=True):
  from qharv.seed import wf_h5
  from qharv.inspect import axes_pos
  from rsgub.grids.forlib.find_gvecs import calc_rhok
  fp = wf_h5.read(fwf)
  axes = wf_h5.get(fp, 'axes')
  # calculate ukbrags
  raxes = axes_pos.raxes(axes)
  kcand = np.dot(kbrags, np.linalg.inv(raxes))
  ukbrags = np.round(kcand).astype(int)
  # check ukbrags
  kbrags1 = np.dot(ukbrags, raxes)
  assert np.allclose(kbrags, kbrags1)
  # calculate rhok
  gvecs = wf_h5.get(fp, 'gvectors')
  ntwist = wf_h5.get(fp, 'nkpt')[ispin]
  # store complex numbers in real view
  data = np.zeros([ntwist, 2*len(ukbrags)])
  if show_progress:
    from progressbar import ProgressBar
    bar = ProgressBar(maxval=ntwist)
  for itwist in range(ntwist):
    cmat = wf_h5.get_cmat(fp, itwist, ispin, norb=norb)
    val = 2*calc_rhok(ukbrags, gvecs, cmat)
    data[itwist, :] = val.view(float)
    if show_progress:
      bar.update(itwist)
  fp.close()
  return data
示例#6
0
def legal_kvecs(axes, nsh, eps=1e-8):
  from qharv.inspect import axes_pos
  raxes = axes_pos.raxes(axes)
  gvecs = axes_pos.cubic_pos(2*nsh+1)-nsh
  kvecs = np.dot(gvecs, raxes)
  kmags = np.linalg.norm(kvecs, axis=-1)
  sel = (kmags>eps) & (kvecs[:, 2]>=0)
  return kvecs[sel]
示例#7
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
示例#8
0
def calc_nk1d_fsc(uk, unkm, nelec, rs=3.25, mx=8):
    from qharv.inspect import axes_pos
    from solith.li_nofk.expt_jofp import flip_and_clamp
    from solith.dft_calc.bcc_crystal import get_cubic_axes
    from chiesa_correction import IsotropicMomentumDistributionFSC
    axes = get_cubic_axes(rs, nelec)
    raxes = axes_pos.raxes(axes)
    fsc = IsotropicMomentumDistributionFSC(rs)
    fsc.init_missing_qvecs(raxes, mx)
    fnk = flip_and_clamp(uk, unkm, kind='linear')
    kvs = np.array([[k, 0, 0] for k in uk])
    dnk_fsc = fsc.evaluate_fsc(fnk, kvs)
    return np.array(dnk_fsc)
示例#9
0
def get_momenta_and_weights(fp, ispin, ikpt, kmax, ecore, efermi):
    """ Histogram psig^2 for a single determinant of Kohn-Sham orbitals at a
  single twist. Select states with momenta k<kmax and energy ecore<e<efermi.

  Args:
    fp (h5py.File): pwscf.pwscf.h5 file pointer
    ispin (int): determinant index (0: unpolarized, 0/1: polarized)
    ikpt (int): twist vector index
    kmax (float): maximum momentum to record
    ecore (float): Core state energy bound. States below ecore are excluded
    efermi (float): Fermi energy
  Return:
    (np.array, np.array): (momenta, weights)
  """
    # get reciprocal lattice vectors to do lattice transformation
    axes = wf_h5.get(fp, 'axes')
    raxes = axes_pos.raxes(axes)
    # Bloch function momenta (kvecs)
    gvecs = wf_h5.get(fp, 'gvectors')
    kvecs = np.dot(gvecs, raxes)
    # crystal momentum (tvec)
    kpath = wf_h5.kpoint_path(ikpt)
    utvec = fp[os.path.join(kpath, 'reduced_k')].value
    tvec = np.dot(utvec, raxes)
    # true momentum = crystal + Bloch momentum
    mykvecs = kvecs + tvec[np.newaxis, :]

    # keep kvectors below kmax
    mykmags = np.linalg.norm(mykvecs, axis=1)
    sel = mykmags < kmax
    momenta = mykvecs[sel]

    # accumulate occupation
    weights = np.zeros(len(momenta))
    # keep states below the Fermi level and outside the core
    nstate = fp[os.path.join(kpath, 'spin_%d' % ispin,
                             'number_of_states')].value[0]
    evals = fp[os.path.join(kpath, 'spin_%d' % ispin, 'eigenvalues')].value
    esel = (evals > ecore) & (evals < efermi)
    states = np.arange(nstate)
    for istate in states[esel]:
        psig = wf_h5.get_orb_in_pw(fp, ikpt, ispin, istate)
        pg2 = psig.conj() * psig
        if not np.allclose(pg2.imag, 0): raise RuntimeError('dot not zero')
        pg2 = pg2.real[sel]
        weights += pg2
    return momenta, weights
示例#10
0
def get_explicit_kpaths(seek_json, dk=0.025):
    """ convert implicit kpath info to explicit list of kpoints
  make simple edits to the JSON file returned from the seeK-path website
  so that it would be accepted by seekpath.getpaths.get_explicit_from_implicit

  example of implicit kpath:
    'path':[
      ['GAMMA', 'H'],
      ['H', 'N'],
      ['N', 'GAMMA'],
      ['GAMMA', 'P'],
      ['P', 'H'],
      ['P', 'N']
    ],
    'kpoints_rel':[
      'GAMMA':[0.0,0.0,0.0],
      'H':[0.5,-0.5,0.5],
      'N':[0.0,0.0,0.5],
      'P':[0.25,0.25,0.25]
    ]

  example of explicity kpath:
    'kpoints_labels':['Gamma','',...,'N'],
    'kpoints_abs': array([
      [0.,0.,0.]
      [0.018,0.,0.018],
      ...,
      [1.618,1.618,3.236]
    ])

  Args:
    seek_json (str): JSON file pasted from seeK-path website
    dk (float, optional): spacing in reciprocal space in Hartree a.u.
  Return:
    dict: return value of seekpath.getpaths.get_explicit_from_implicit
  """
    from qharv.inspect import axes_pos  # need raxes
    with open(seek_json, 'r') as f:
        data = json.load(f)
    # end with
    data['point_coords'] = data['kpoints']
    data['reciprocal_primitive_lattice'] = axes_pos.raxes(
        data['primitive_lattice'])
    kpaths = seekpath.getpaths.get_explicit_from_implicit(data, dk)
    return kpaths
示例#11
0
def write_detsk(h5file, ikpt, fwf, ispin, nsh0, kc):
  """Calculate determinant S(k) at given twist

  Args:
    h5file (tables.file.File): hdf5 file handle
    ikpt (int): twist index
    fwf (str): wf h5 file e.g. pwscf.pwscf.h5
    ispin (int): spin index, use 0 for unpolarized
    nsh0 (int): number of shells to use
    kc (float): PW cutoff
  """
  from qharv.seed import wf_h5
  from qharv.inspect.axes_pos import raxes
  from qharv.reel.config_h5 import save_dict
  from solith.li_nofk.forlib.det import calc_detsk
  from chiesa_correction import mirror_xyz, cubic_pos
  # creat slab for twist
  gname = 'twist%s' % str(ikpt).zfill(3)
  slab = h5file.create_group('/', gname, '')

  # read wf file
  fp = wf_h5.read(fwf)
  gvecs = wf_h5.get(fp, 'gvectors')
  cmat = wf_h5.get_cmat(fp, ikpt, ispin)
  wf_h5.normalize_cmat(cmat)
  axes = wf_h5.get(fp, 'axes')
  fp.close()
  raxes = raxes(axes)

  # decide which qvectors to calculate S(q)
  qvecs = mirror_xyz(cubic_pos(nsh0))
  kvecs = np.dot(qvecs, raxes)
  kmags = np.linalg.norm(kvecs, axis=-1)
  qsel = (1e-8 < kmags) & (kmags < kc)

  # calculate S(k)
  sk0 = calc_detsk(qvecs[qsel],  gvecs, cmat)

  # save
  arr_dict = {
    'raxes': raxes,
    'gvecs': qvecs[qsel],
    'sk0': sk0
  }
  save_dict(arr_dict, h5file, slab)
示例#12
0
def get_det_nk(fp, efermi, ecore=-np.inf, kmax=np.inf, ispin=0):
    """Calculate momentum distribution from Kohn-Sham determinant

  same as get_momentum_distribution, but faster

  Args:
    fp (h5py.File): pwscf.pwscf.h5 file pointer
    efermi (float): Fermi energy
    ecore (float, optional): core energy, default -np.inf
    kmax (float, optional): maximum k magnitude to record, default np.inf
    ispin (int, optiona): default 0
  Return:
    (np.array, np.array): (kvecs, nkm), kvectors and n(k) mean (no error)
  """
    from solith.li_nofk.forlib.det import nofk
    # need Kohn-Sham eigenvalues to decide which states to use
    bands = wf_h5.get_bands(fp, ispin=ispin)
    nt, nstate = bands.shape

    # need kgrid info: basis (raxes), unshifted (kvecs0), twists (tvecs)
    axes = wf_h5.get(fp, 'axes')
    raxes = axes_pos.raxes(axes)
    gvecs = wf_h5.get(fp, 'gvectors')
    utvecs = wf_h5.get_twists(fp)
    tvecs = np.dot(utvecs, raxes)
    kvecs0 = np.dot(gvecs, raxes)

    # calculate n(k) at each twist
    kvecsl = []
    nkml = []
    for it in range(nt):
        kvecs = kvecs0 + tvecs[it]  # current twist
        # histogram orb^2
        cmat = wf_h5.get_cmat(fp, it, ispin, nstate)
        nocc, npw = cmat.shape
        weights = nofk(kvecs, cmat, bands[it], kmax, ecore, efermi)
        # save within a cutoff
        kmags = np.linalg.norm(kvecs, axis=-1)
        sel = kmags < kmax
        kvecsl.append(kvecs[sel])
        nkml.append(weights[sel])

    kvecs = np.concatenate(kvecsl, axis=0)
    nkm = np.concatenate(nkml)
    return kvecs, nkm
示例#13
0
def get_rhok(fwf, kbrags, norb=None, itwist=0, ispin=0):
  from qharv.seed import wf_h5
  from qharv.inspect import axes_pos
  from rsgub.grids.forlib.find_gvecs import calc_rhok
  fp = wf_h5.read(fwf)
  axes = wf_h5.get(fp, 'axes')
  gvecs = wf_h5.get(fp, 'gvectors')
  cmat = wf_h5.get_cmat(fp, itwist, ispin, norb=norb)
  fp.close()
  # calculate ukbrags
  raxes = axes_pos.raxes(axes)
  kcand = np.dot(kbrags, np.linalg.inv(raxes))
  ukbrags = np.round(kcand).astype(int)
  # check ukbrags
  kbrags1 = np.dot(ukbrags, raxes)
  assert np.allclose(kbrags, kbrags1)
  # calculate rhok
  val = 2*calc_rhok(ukbrags, gvecs, cmat)
  return val
示例#14
0
def get_bands(nscf_out, tgrid0):
    """Get bands and kgrid info from nscf output

  data contains: kvecs, bands, tgrid, raxes, gvecs
  kvecs (nk, ndim) are reciprocal points possible in the irreducible wedge
   kvecs are in 2\pi/alat units
  bands (nk, nstate) are the Kohn-Sham eigenvalues
   bands are in eV units
  tgrid (ndim) is grid size in each dimension
   !!!! currently assumed to be the same as x
  raxes (ndim, ndim) is the reciprocal lattice
  gvecs (nk, ndim) are reciprocal lattice points (kvecs) converted to integers

  Args:
    nscf_out (str): output file
    tgrid0 (int): grid along x
  Return:
    dict: data
  """
    from qharv.inspect import axes_pos
    import qe_reader as qer
    # get bands
    data = qer.parse_nscf_bands(nscf_out)
    kvecs = data['kvecs']

    # get raxes, gvecs
    tgrid = np.array([tgrid0] * 3)
    axes = qer.read_out_cell(nscf_out)
    raxes = axes_pos.raxes(axes)

    gcand = np.dot(kvecs, np.linalg.inv(raxes / tgrid))
    gvecs = np.around(gcand).astype(int)

    data['tgrid'] = tgrid
    data['raxes'] = raxes
    data['gvecs'] = gvecs
    data.pop('nkpt')
    return data
示例#15
0
def get_tgrid_raxes(nscf_in, ndim=3):
    from qharv.inspect import axes_pos
    tgrid, tshift = get_tgrid_tshift(nscf_in)
    axes = get_axes(nscf_in, ndim=ndim)
    raxes = axes_pos.raxes(axes)
    return tgrid, raxes