Periodic and Isolated Calculations with GPAW

CiderPress integrates with the classic GPAW [1] calculator in plane-wave mode. The supported route uses PAW setups so the nonlocal descriptors include the all-electron core-region information described in Numerical Evaluation in PySCF and GPAW.

Functional construction

CIDER26XC is a full-XC model. Construct it with the composition stored in the model:

xc = get_cider_functional(
    "CIDER26XCSURFSCI",
    xmix=1.0,
    xkernel=None,
    ckernel=None,
    pasdw_store_funcs=False,
)

For an exchange-only CIDER23X model, retain an explicit PBE0/CIDER composition:

xc = get_cider_functional(
    "CIDER23X_NL_MGGA_DTR",
    xmix=0.25,
    xkernel="GGA_X_PBE",
    ckernel="GGA_C_PBE",
)

The GPAW interface evaluates NLDF models. CIDER24X uses the PySCF SDMX path, and CIDER26XCCHEMD4 uses the PySCF D4 energy interface.

The CIDER23X pseudopotential route used in earlier band-gap work remains available for methodological reproduction:

 1#!/usr/bin/env python
 2"""CIDER23X pseudopotential calculation for methodological reproduction."""
 3
 4from ase.build import bulk
 5from ase.parallel import parprint
 6from gpaw import PW
 7
 8from ciderpress.gpaw.calculator import CiderGPAW, get_cider_functional
 9
10
11def main():
12    atoms = bulk("Si")
13    xc = get_cider_functional(
14        "CIDER23X_NL_MGGA_DTR",
15        xmix=0.25,
16        xkernel="GGA_X_PBE",
17        ckernel="GGA_C_PBE",
18        use_paw=False,
19    )
20    atoms.calc = CiderGPAW(
21        mode=PW(520),
22        xc=xc,
23        setups="sg15",
24        h=0.13,
25        kpts={"size": (12, 12, 12), "gamma": False},
26        occupations={"name": "fermi-dirac", "width": 0.01},
27        convergence={"energy": 1e-5},
28        parallel={"augment_grids": True},
29        txt="si_cider23_pp.txt",
30    )
31    energy = atoms.get_potential_energy()
32    parprint(f"CIDER23X pseudopotential energy = {energy:.12f} eV")
33
34
35if __name__ == "__main__":
36    main()

The production CIDER26XC route uses PAW so its nonlocal descriptors include the all-electron augmentation-region contribution.

PBE-seeded periodic workflow

The periodic example evaluates PBE and writes its wavefunctions with mode="all" before constructing the CIDER functional and restarting:

 1#!/usr/bin/env python
 2"""PBE-seeded periodic CIDER26XCSURFSCI calculation in classic GPAW."""
 3
 4from ase.build import bulk
 5from ase.parallel import parprint
 6from gpaw import GPAW, PW, Mixer
 7
 8from ciderpress.gpaw.calculator import CiderGPAW, get_cider_functional
 9
10
11def main():
12    atoms = bulk("Si")
13    atoms.calc = GPAW(
14        xc="PBE",
15        mode=PW(400),
16        kpts={"size": (4, 4, 4), "gamma": False},
17        occupations={"name": "fermi-dirac", "width": 0.1},
18        mixer=Mixer(0.05, 5, 50),
19        convergence={
20            "energy": 1e-5,
21            "density": 1e-5,
22            "eigenstates": 1e-3,
23            "bands": "occupied",
24        },
25        parallel={"augment_grids": True},
26        txt="si_pbe.txt",
27    )
28    atoms.get_potential_energy()
29    # The production models are meta-GGAs and need the wavefunctions to
30    # reconstruct the kinetic-energy density after restart.
31    atoms.calc.write("si_pbe.gpw", mode="all")
32
33    xc = get_cider_functional(
34        "CIDER26XCSURFSCI",
35        xmix=1.0,
36        xkernel=None,
37        ckernel=None,
38        pasdw_store_funcs=False,
39    )
40    calc = CiderGPAW(
41        restart="si_pbe.gpw",
42        xc=xc,
43        mixer=Mixer(0.05, 5, 50),
44        occupations={"name": "fermi-dirac", "width": 0.1},
45        maxiter=500,
46        parallel={"augment_grids": True},
47        txt="si_cider.txt",
48    )
49    atoms = calc.get_atoms()
50    atoms.calc = calc
51    energy = atoms.get_potential_energy()
52    calc.write("si_cider.gpw", mode="all")
53    parprint(f"CIDER26XCSURFSCI energy = {energy:.12f} eV")
54
55
56if __name__ == "__main__":
57    main()

Use CiderGPAW for checkpointed calculations; it saves the CIDER-specific restart information. A normal GPAW calculator can evaluate an in-memory CIDER object within the current process.

Surfaces and adsorption systems

The surface template uses a dipole correction, a slab-adapted k-point mesh, and separate PBE and CIDER checkpoints:

 1#!/usr/bin/env python
 2"""PBE-seeded CIDER26XCSURFSCI template for a CO/Pt(111) slab."""
 3
 4from ase.build import add_adsorbate, fcc111, molecule
 5from ase.parallel import parprint
 6from gpaw import GPAW, PW, Mixer
 7
 8from ciderpress.gpaw.calculator import CiderGPAW, get_cider_functional
 9
10
11def main():
12    slab = fcc111("Pt", size=(2, 2, 3), vacuum=8.0)
13    add_adsorbate(slab, molecule("CO"), height=1.85, position="ontop")
14
15    mixer = Mixer(0.03, 5, 100)
16    occupations = {"name": "fermi-dirac", "width": 0.1}
17    convergence = {
18        "energy": 1e-5,
19        "density": 1e-5,
20        "eigenstates": 1e-3,
21        "bands": "occupied",
22    }
23    slab.calc = GPAW(
24        xc="PBE",
25        mode=PW(450),
26        kpts={"size": (4, 4, 1), "gamma": True},
27        occupations=occupations,
28        mixer=mixer,
29        convergence=convergence,
30        maxiter=500,
31        poissonsolver={"dipolelayer": "xy"},
32        parallel={"augment_grids": True},
33        txt="co_pt_pbe.txt",
34    )
35    slab.get_potential_energy()
36    slab.calc.write("co_pt_pbe.gpw", mode="all")
37
38    xc = get_cider_functional(
39        "CIDER26XCSURFSCI",
40        xmix=1.0,
41        xkernel=None,
42        ckernel=None,
43        pasdw_store_funcs=False,
44    )
45    calc = CiderGPAW(
46        restart="co_pt_pbe.gpw",
47        xc=xc,
48        occupations=occupations,
49        mixer=Mixer(0.03, 5, 100),
50        convergence=convergence,
51        maxiter=500,
52        parallel={"augment_grids": True},
53        txt="co_pt_cider.txt",
54    )
55    slab = calc.get_atoms()
56    slab.calc = calc
57    energy = slab.get_potential_energy()
58    calc.write("co_pt_cider.gpw", mode="all")
59    parprint(f"CIDER26XCSURFSCI energy = {energy:.12f} eV")
60
61
62if __name__ == "__main__":
63    main()

Isolated systems in periodic boxes

The isolated-system example places an atom in a 12 Angstrom cubic cell and uses Gamma-point sampling:

 1#!/usr/bin/env python
 2"""Isolated molecule in a periodic box with classic GPAW and CIDER."""
 3
 4from ase import Atoms
 5from ase.parallel import parprint
 6from gpaw import GPAW, PW, Mixer
 7from gpaw.eigensolvers.davidson import Davidson
 8
 9from ciderpress.gpaw.calculator import CiderGPAW, get_cider_functional
10
11
12def main():
13    atoms = Atoms("He")
14    atoms.set_cell((12.0, 12.0, 12.0))
15    atoms.center()
16    atoms.pbc = True
17
18    mixer = Mixer(0.05, 5, 50)
19    occupations = {"name": "fermi-dirac", "width": 0.01}
20    convergence = {
21        "energy": 5e-4,
22        "density": 1e-4,
23        "eigenstates": 5e-3,
24        "bands": "occupied",
25    }
26    # This example uses a relaxed baseline density criterion before the CIDER
27    # restart.  Converge both stages for the target property.
28    pbe_convergence = dict(convergence)
29    pbe_convergence["density"] = 1e-2
30    atoms.calc = GPAW(
31        xc="PBE",
32        mode=PW(400),
33        kpts={"size": (1, 1, 1), "gamma": True},
34        symmetry="off",
35        mixer=mixer,
36        eigensolver=Davidson(niter=3),
37        occupations=occupations,
38        convergence=pbe_convergence,
39        maxiter=500,
40        parallel={"augment_grids": True},
41        txt="he_pbe.txt",
42    )
43    atoms.get_potential_energy()
44    # Preserve wavefunctions for the meta-GGA kinetic-energy density.
45    atoms.calc.write("he_pbe.gpw", mode="all")
46
47    xc = get_cider_functional(
48        "CIDER26XCSURFSCI",
49        xmix=1.0,
50        xkernel=None,
51        ckernel=None,
52        pasdw_store_funcs=False,
53    )
54    calc = CiderGPAW(
55        restart="he_pbe.gpw",
56        xc=xc,
57        mixer=Mixer(0.05, 5, 50),
58        eigensolver=Davidson(niter=3),
59        occupations=occupations,
60        convergence=convergence,
61        maxiter=500,
62        parallel={"augment_grids": True},
63        txt="he_cider.txt",
64    )
65    atoms = calc.get_atoms()
66    atoms.calc = calc
67    energy = atoms.get_potential_energy()
68    # Keep wavefunctions so a later meta-GGA restart can reconstruct the
69    # kinetic-energy density.
70    calc.write("he_cider.gpw", mode="all")
71    parprint(f"CIDER26XCSURFSCI energy = {energy:.12f} eV")
72
73
74if __name__ == "__main__":
75    main()

For small neutral compact systems, 12–15 Angstrom is a practical initial box size. Charged or diffuse systems generally require a larger cell and an appropriate finite-size electrostatic treatment.

Restarting a CIDER checkpoint

Write both baseline and CIDER meta-GGA calculations with mode="all". To continue a CIDER checkpoint, construct a fresh functional and pass it when the calculator is recreated:

 1#!/usr/bin/env python
 2"""Continue the CIDER checkpoint produced by production_calc.py."""
 3
 4from ase.parallel import parprint
 5from gpaw import Mixer
 6
 7from ciderpress.gpaw.calculator import CiderGPAW, get_cider_functional
 8
 9
10def main():
11    xc = get_cider_functional(
12        "CIDER26XCSURFSCI",
13        xmix=1.0,
14        xkernel=None,
15        ckernel=None,
16        pasdw_store_funcs=False,
17    )
18    calc = CiderGPAW(
19        restart="si_cider.gpw",
20        xc=xc,
21        mixer=Mixer(0.05, 5, 50),
22        maxiter=500,
23        parallel={"augment_grids": True},
24        txt="si_cider_restart.txt",
25    )
26    atoms = calc.get_atoms()
27    atoms.calc = calc
28    energy = atoms.get_potential_energy()
29    calc.write("si_cider_restarted.gpw", mode="all")
30    parprint(f"restarted CIDER26XCSURFSCI energy = {energy:.12f} eV")
31
32
33if __name__ == "__main__":
34    main()

The checkpoint stores the mapped model text and nonlocal interpolation parameters, including Nalpha, lambd, and the plane-wave cutoff encut derived from the qmax argument. Opening the checkpoint with its saved XC setting makes CiderGPAW reconstruct the saved CIDER functional. An explicit xc= argument selects the functional for the resumed calculation.

Forces and stress

ASE’s normal get_forces() and get_stress() calls include the CIDER FFT and PAW derivative contributions for the supported PAW path. See Energies and Derivative Properties, which includes the complete examples/gpaw/forces_stress.py template.

PASDW and interpolation controls

pasdw_store_funcs=False is the memory-saving default. Setting it to True caches atomic projector functions and can reduce repeated cost at substantial memory expense. pasdw_ovlp_fit=True selects overlap fitting for the projection. Both options are part of the PAW numerical representation.

qmax and lambd control the expansion of the nonlocal kernel. Smaller lambd gives denser interpolation and higher cost. Nalpha is normally determined automatically.

Parallel execution and memory

Use parallel={"augment_grids": True} to distribute XC grid work. The nonlocal FFT buffers and PAW data add memory beyond a comparable PBE calculation. For memory-heavy systems, run each restart attempt as a separate job so memory from the previous calculator is released.

The CiderPress extension and GPAW must use compatible MPI, FFT, BLAS, and OpenMP runtimes.

SCF strategy

Handling SCF Convergence Issues lists the mixer, eigensolver, occupation, and restart settings used by the bulk, surface, isolated-system, and magnetic fallback examples.