Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
bcfa5e6
add pwscf to pyscf-forge
kylebystrom Jun 15, 2025
ea9598e
move new pseudo
kylebystrom Jun 15, 2025
105e436
init files
kylebystrom Jun 18, 2025
5a40005
draft occupation smearing
kylebystrom Jun 18, 2025
1219398
add metal example
kylebystrom Jun 18, 2025
6abd022
fix smearing for unrestricted case
kylebystrom Jun 18, 2025
414dd82
update unit test
kylebystrom Jun 18, 2025
47ea098
draft kpt-sym density generation
kylebystrom Jul 3, 2025
96dd446
update lib
kylebystrom Jul 3, 2025
cfd3229
kpt symmetry-adapted PW mode for RHF and RKS (draft for UHF and UKS)
kylebystrom Jul 8, 2025
9c2b8ca
SG15 pseudos, PW cutoff options, clean up symmetry stuff
kylebystrom Jul 14, 2025
8e89b4a
abstraction for coarse to dense grid and vice versa
kylebystrom Jul 31, 2025
32f7609
add license headers/authorship, refactor unit tests
kylebystrom Aug 8, 2025
e8bcda8
fix bug in khf and mixer in pw_helper
kylebystrom Aug 9, 2025
c71ac4a
fix minor bugs and update unit tests
kylebystrom Aug 9, 2025
a0ae58b
get the pwscf unit tests working with pyscf master branch
kylebystrom Sep 3, 2025
fe89b8e
refactor and fix some smearing/UKS/UHF issues
kylebystrom Sep 4, 2025
0055849
refactor khf, mp2 and ccsd with ecut_wf, dump/load changes in ncpp_ce…
kylebystrom Sep 6, 2025
cb14caf
fix up ncpp_cell and unit tests
kylebystrom Sep 6, 2025
df27d3b
speed up some unit tests
kylebystrom Sep 8, 2025
65e7f79
avoid double-loop for pure XC functionals w/o ccecp and update tests
kylebystrom Sep 8, 2025
823e43f
clean up modules, address TODO items, fix G=0 term of SG15 pseudo
kylebystrom Sep 9, 2025
573f63a
add documentation, update license headers, fix ecut_rho
kylebystrom Sep 9, 2025
ce71cbe
fix occupations for unrestricted case
kylebystrom Sep 9, 2025
8802ac2
pwscf code cleanup and examples
kylebystrom Sep 10, 2025
b911358
fix merge conflicts and tests
kylebystrom Sep 10, 2025
8863415
update pwscf README
kylebystrom Sep 10, 2025
fa4e5f9
fix contact emails
kylebystrom Sep 11, 2025
5fdb42d
fix flake/lint/ruff
kylebystrom Sep 13, 2025
47f5c37
remove unneeded files messing with tests
kylebystrom Sep 13, 2025
2c02630
Merge branch 'master' into pwscf_pr
kylebystrom Sep 13, 2025
4e21767
remove unneeded __init__ and use sph_harm_y for SG15 pseudos
kylebystrom Sep 15, 2025
069b29c
fix whitespace and deprecated numpy function
kylebystrom Sep 15, 2025
6d0be7a
fix spherical harmonics big for ncpp_cell
kylebystrom Sep 15, 2025
8969c39
adjust unit test prec
kylebystrom Sep 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions examples/pwscf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Plane-Wave Mode

The `pyscf.pbc.pwscf` module provides experimental support for Hartree-Fock (HF),
density functional theory (DFT), second-order Møller-Plesset perturbation theory (MP2),
and coupled cluster singles doubles (CCSD) in a plane-wave basis.
The CCECP and GTH pseudopotentials are supported for these methods,
and SG15 pseudopotentials are supported for HF and DFT calculations.
Occupation smearing and symmetry reduction of k-point meshes are implemented for HF and DFT.

## Feature Overview

The following self-consistent field (SCF) calculations are supported:
* Hartree-fock (Restricted and Unrestricted)
* Kohn-Sham DFT (Restricted and Unrestricted), with LDA, GGA, MGGA, and global hybrid functionals

Currently, the Davidson algorithm is implemented for the effective Hamiltonian diagonalization.
There are two mixing schemes for the effective potential, "Simple" and "Anderson" (DIIS).
Symmetry reduction of k-points is supported for SCF calculations, along with occupation
smearing. The default plane-wave basis set and integration grid are determined by `cell.mesh`,
but these can be customized using the energy cutoffs `ecut_wf` and `ecut_rho` or by setting
meshes directly using `PWKSCF.set_meshes()`.

The following post-SCF calculations are supported:
* MP2 (Restricted and Unrestricted)
* CCSD (Restricted only)

K-point symmetry and occupation smearing are currently not supported for post-SCF
methods. The `PWKSCF.get_cpw_virtual()` method can be used to create virtual
molecular orbitals in a GTO basis for use in post-SCF calculations.

Plane-wave calculations can be performed with GTH or CCECP pseudopotentials
(or all-electron for very small atoms). There is also basic support for SG15
norm-conserving pseudopotentials. The post-SCF methods have been tested with GTH
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be helpful to include some explanations about where to download the SG15 database and how to configure the path since this database is not included in the source code.

and CCECP but not SG15, while the SCF methods have been tested with GTH, CCECP, and SG15.

38 changes: 38 additions & 0 deletions examples/pwscf/al.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from pyscf.pbc import gto
from pyscf.pbc.pwscf.smearing import smearing_
from pyscf.pbc.pwscf import kpt_symm
import numpy as np

"""
Simple examples of running DFT for FCC Al. Uses
k-point symmetrt and smearing
"""

cell = gto.Cell()
cell.a = 4.0 * np.eye(3)
x = 2.0
cell.atom = f"""
Al 0 0 0
Al 0 {x} {x}
Al {x} 0 {x}
Al {x} {x} 0
"""
cell.pseudo = 'gth-pade'
cell.basis = 'gth-szv'
cell.verbose = 4
cell.space_group_symmetry = True
cell.symmorphic = True
cell.build()

kpts = cell.make_kpts(
[4, 4, 4],
time_reversal_symmetry=True,
space_group_symmetry=True
)
kmf = kpt_symm.KsymAdaptedPWKRKS(cell, kpts, ecut_wf=40)
kmf = smearing_(kmf, sigma=0.01, method='gauss')
kmf.xc = "PBE"
kmf.nvir = 2
kmf.conv_tol = 1e-7
kmf.kernel()
kmf.dump_scf_summary()
34 changes: 34 additions & 0 deletions examples/pwscf/kccsd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import numpy as np
from pyscf.pbc import cc
from pyscf.pbc.pwscf.pw_helper import gtomf2pwmf
from pyscf.pbc.pwscf.kccsd_rhf import PWKRCCSD

"""
Simple CCSD calculation
"""

a0 = 1.78339987
atom = "C 0 0 0; C %.10f %.10f %.10f" % (a0*0.5, a0*0.5, a0*0.5)
a = np.asarray([
[0., a0, a0],
[a0, 0., a0],
[a0, a0, 0.]])

from pyscf.pbc import gto, scf, pwscf
cell = gto.Cell(atom=atom, a=a, basis="gth-szv", pseudo="gth-pade",
ke_cutoff=50)
cell.build()
cell.verbose = 5

kpts = cell.make_kpts([2,1,1])

mf = scf.KRHF(cell, kpts)
mf.kernel()

mcc = cc.kccsd_rhf.RCCSD(mf)
mcc.kernel()

pwmf = gtomf2pwmf(mf)
pwmcc = PWKRCCSD(pwmf).kernel()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pwkrccsd can be started from a regular pwscf.PWKRHF(cell, kpts) calculation, right? I think this "normal" usage can be demonstrated . And the conversion between the GTO-KHF can then be demonstrated, with some explanation comments.


assert(np.abs(mcc.e_corr - pwmcc.e_corr) < 1e-5)
40 changes: 40 additions & 0 deletions examples/pwscf/kmp2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pyscf.pbc import gto, pwscf
from pyscf.pbc.pwscf.kmp2 import PWKRMP2
import numpy as np

"""
Simple MP2 calculation
"""

atom = "H 0 0 0; H 0.9 0 0"
a = np.eye(3) * 3
basis = "gth-szv"
pseudo = "gth-pade"

ke_cutoff = 50

cell = gto.Cell(atom=atom, a=a, basis=basis, pseudo=pseudo,
ke_cutoff=ke_cutoff)
cell.build()
cell.verbose = 6

nk = 2
kmesh = [nk] * 3
kpts = cell.make_kpts(kmesh)
nkpts = len(kpts)

pwmf = pwscf.PWKRHF(cell, kpts)
pwmf.nvir = 20
pwmf.kernel()

es = {"5": -0.01363871, "10": -0.01873622, "20": -0.02461560}

pwmp = PWKRMP2(pwmf)
pwmp.kernel(nvir_lst=[5,10,20])
pwmp.dump_mp2_summary()
nvir_lst = pwmp.mp2_summary["nvir_lst"]
ecorr_lst = pwmp.mp2_summary["e_corr_lst"]
for nvir,ecorr in zip(nvir_lst,ecorr_lst):
err = abs(ecorr - es["%d"%nvir])
print(err)
assert(err < 1e-5)
56 changes: 56 additions & 0 deletions examples/pwscf/kpt_symm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from pyscf.pbc import gto
from pyscf.pbc.pwscf.khf import PWKRHF
from pyscf.pbc.pwscf.kpt_symm import KsymAdaptedPWKRHF
import numpy as np
import time

"""
Demonstrate the speedup of symmetry-adapted HF over
non-symmetry-adapted HF.
"""

cell = gto.Cell(
atom = "C 0 0 0; C 0.89169994 0.89169994 0.89169994",
a = np.asarray([
[0. , 1.78339987, 1.78339987],
[1.78339987, 0. , 1.78339987],
[1.78339987, 1.78339987, 0. ]]),
basis="gth-szv",
ke_cutoff=50,
pseudo="gth-pade",
verbose=4,
space_group_symmetry=True,
symmorphic=True,
)
cell.build()

kmesh = [2, 2, 2]
center = [0, 0, 0]
kpts = cell.make_kpts(kmesh)
skpts = cell.make_kpts(
kmesh,
scaled_center=center,
space_group_symmetry=True,
time_reversal_symmetry=True,
)

mf = PWKRHF(cell, kpts, ecut_wf=40)
mf.nvir = 4
t0 = time.monotonic()
mf.kernel()
t1 = time.monotonic()

mf2 = KsymAdaptedPWKRHF(cell, skpts, ecut_wf=20)
mf2.damp_type = "simple"
mf2.damp_factor = 0.7
mf2.nvir = 4
t2 = time.monotonic()
mf2.kernel()
t3 = time.monotonic()

print(mf.e_tot, mf2.e_tot)
mf.dump_scf_summary()
mf2.dump_scf_summary()
print("nkpts in BZ and IBZ", skpts.nkpts, skpts.nkpts_ibz)
print("Runtime without symmmetry", t1 - t0)
print("Runtime with symmetry", t3 - t2)
61 changes: 61 additions & 0 deletions examples/pwscf/li.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from pyscf.pbc import gto
from pyscf.gto.basis import parse_cp2k_pp
from pyscf.pbc.pwscf import kpt_symm, khf, smearing
import numpy as np

"""
Simple examples of running HF and DFT for BCC Li.
Both calculations run with smearing.
The DFT calculation handles a larger k-mesh with
k-point symmetry.
"""

cell = gto.Cell()
a = 3.4393124531669552
cell.a = a * np.eye(3)
x = 0.5 * a
cell.atom = f"""
Li 0 0 0
Li {x} {x} {x}
"""
cell.pseudo = {'Li': parse_cp2k_pp.parse("""
#PSEUDOPOTENTIAL
Li GTH2-HF-q1
1 0 0 0
0.75910286326041 2 -1.83343584669401 0.32295157976066
2
0.66792517034256 1 1.83367870276199
1.13098354939590 1 -0.00004141168540
""")}
cell.basis = 'gth-szv'
cell.verbose = 4
cell.space_group_symmetry = True
cell.symmorphic = True
cell.mesh = [10, 10, 10]
cell.build()

# Center at the Baldereshi point
kpts = cell.make_kpts(
[2, 2, 2],
scaled_center=[1.0/6, 1.0/6, 0.5]
)
kmf = khf.PWKRHF(cell, kpts, ecut_wf=40)
kmf = smearing.smearing_(kmf, sigma=0.02, method='gauss')
kmf.xc = "PBE"
kmf.conv_tol = 1e-7
kmf.conv_tol_grad = 2e-3
ehf = kmf.kernel()

kpts = cell.make_kpts(
[4, 4, 4],
scaled_center=[1.0/6, 1.0/6, 0.5],
time_reversal_symmetry=True,
space_group_symmetry=True
)
kmf = kpt_symm.KsymAdaptedPWKRKS(cell, kpts, ecut_wf=40)
kmf = smearing.smearing_(kmf, sigma=0.01, method='gauss')
kmf.xc = "PBE"
kmf.conv_tol = 1e-7
kmf.conv_tol_grad = 2e-3
ehf = kmf.kernel()

32 changes: 32 additions & 0 deletions examples/pwscf/set_meshes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from pyscf.pbc import gto
from pyscf.pbc.pwscf.krks import PWKRKS
import numpy as np

"""
This example demonstrates converging the energy with respect to
the mesh size. Note that
"""

cell = gto.Cell(
atom = "C 0 0 0; C 0.89169994 0.89169994 0.89169994",
a = np.asarray([
[0. , 1.78339987, 1.78339987],
[1.78339987, 0. , 1.78339987],
[1.78339987, 1.78339987, 0. ]]),
basis="gth-szv",
ke_cutoff=50,
pseudo="gth-pade",
)

kmesh = [2, 1, 1]
kpts = cell.make_kpts(kmesh)

mf = PWKRKS(cell, kpts)

# defaults
print(cell.mesh, mf.wf_mesh, mf.xc_mesh)
mf.kernel()

mf.set_meshes(wf_mesh=[15, 15, 15], xc_mesh=[33, 33, 33])
print(mf.wf_mesh, mf.xc_mesh)
mf.kernel()
82 changes: 82 additions & 0 deletions examples/pwscf/sg15.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from pyscf.pbc import gto
from pyscf.pbc.pwscf.krks import PWKRKS
# from pyscf.pbc.pwscf.kpt_symm import KsymAdaptedPWKRKS as PWKRKS
from pyscf.pbc.pwscf.ncpp_cell import NCPPCell
import numpy as np

"""
This example demonstrates the convergence of the total
energy with respect to plane-wave energy cutoff for
GTH and SG15 pseudopotentials. The SG15 converges
faster, especially up to a 1000 eV cutoff (36.76 Ha),
because these potentials were designed to converge more
quickly.

NOTE: Before using this example, you must set
pbc_pwscf_ncpp_cell_sg15_path in your pyscf config file.
"""

kwargs = dict(
atom = "C 0 0 0; C 0.89169994 0.89169994 0.89169994",
a = np.asarray([
[0. , 1.78339987, 1.78339987],
[1.78339987, 0. , 1.78339987],
[1.78339987, 1.78339987, 0. ]]),
basis="gth-szv",
ke_cutoff=50,
pseudo="gth-pade",
verbose=0,
)

cell = gto.Cell(**kwargs)
cell.build()

kwargs.pop("pseudo")
nccell = NCPPCell(**kwargs)
nccell.build()

kmesh = [2, 2, 2]
kpts = cell.make_kpts(kmesh)

ens1 = []
ens2 = []
# A larger set of ecuts below is provided in case it's useful.
# ecuts = [18.38235294, 22.05882353, 25.73529412, 29.41176471, 33.08823529,
# 36.76470588, 44.11764706, 55.14705882, 73.52941176, 91.91176471]
ecuts = [18.38235294, 25.73529412, 33.08823529, 36.76470588, 55.14705882]
for ecut in ecuts:
print("ECUT", ecut)
# Run the GTH calculations
mf = PWKRKS(cell, kpts, xc="PBE", ecut_wf=ecut)
mf.damp_type = "simple"
mf.damp_factor = 0.7
mf.nvir = 4 # converge first 4 virtual bands
mf.kernel()
ens1.append(mf.e_tot)

# Run the SG15 calculations
mf2 = PWKRKS(nccell, kpts, xc="PBE", ecut_wf=ecut)
mf2.damp_type = "simple"
mf2.damp_factor = 0.7
mf2.nvir = 4 # converge first 4 virtual bands
mf2.init_pp()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The init_pp and init_jk are automatically called within the scf() method, aren't they? Why do the explicitly called here? Can they be skipped?

mf2.init_jk()
mf2.kernel()
ens2.append(mf2.e_tot)
print(mf.e_tot, mf2.e_tot)
print()

print()
print("GTH Total Energies (Ha)")
print(ens1)
print("Energy cutoffs (Ha)")
print(ecuts[:-1])
print("Differences vs Max Cutoff (Ha)")
print(np.array(ens1[:-1]) - ens1[-1])
print()
print("SG15 Total Energies (Ha)")
print(ens2)
print("Energy cutoffs (Ha)")
print(ecuts[:-1])
print("Differences vs Max Cutoff (Ha)")
print(np.array(ens2[:-1]) - ens2[-1])
1 change: 1 addition & 0 deletions pyscf/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,5 @@ set_target_properties (clib_csf PROPERTIES
OUTPUT_NAME "csf")

add_subdirectory(sfnoci)
add_subdirectory(pwscf)

Loading