Skip to main content

ASE Calculator for TURBOMOLE's RIPER module

Project description

RIPER: ASE Calculator for TURBOMOLE

riper is an ASE calculator interface for the RIPER module in TURBOMOLE. It lets you run RIPER DFT calculations from normal ASE workflows for molecules, chains, slabs, and bulk periodic systems.

The calculator writes TURBOMOLE coord and control files, runs riper, parses energies, forces, stresses, and the final Fermi-level band gap, and returns the results in ASE units.

Features

  • Molecular and periodic RIPER calculations through ASE.
  • Automatic periodicity detection from atoms.pbc.
  • 0D, 1D, 2D, and 3D systems.
  • Energies in eV.
  • Forces in eV/Angstrom.
  • Stress in eV/Angstrom^3 for periodic systems with $optcell.
  • Final band gap parsing from the RIPER Fermi Level Statistics (eV) block.
  • Band gap stored in both calc.results["band_gap"] and atoms.info["band_gap"], so ASE extXYZ exports include it automatically.
  • DFT-D3 support through disp3=True.
  • Density cube generation through plot_dens=True.
  • Electric dipole moments through dipole=True and ASE atoms.get_dipole_moment().
  • UKS calculations through uks=True.
  • Gaussian smearing through smear=True and sigma=....
  • RI integral memory control through $ricore via ricore=... in MB.
  • Optional per-calculation SMP/OpenMP thread control through ncore=....
  • Arbitrary RIPER keywords through extra_keywords.
  • Works with normal ASE optimizers, cell filters, trajectories, NEB workflows, and file I/O.

Installation

From PyPI:

pip install riper

For development from this repository:

pip install -e .

or, with uv:

uv pip install -e .

TURBOMOLE Environment

Before using the calculator, make sure TURBOMOLE is configured in the shell where Python runs. For example:

export TURBODIR=/path/to/TURBOMOLE
export TURBOIMG=/path/to/TURBOMOLE
source $TURBODIR/Config_turbo_env
command -v riper_smp

The calculator does not ship TURBOMOLE. It calls the executable selected with riper_command, for example riper, riper_smp, riper_omp, or a full path.

Quick Start: Water Single Point

from ase.build import molecule
from riper import RIPERCalculator

water = molecule("H2O")
water.calc = RIPERCalculator(
    functional="pbe",
    basis="def2-SVP",
    auxbasis="universal",
    riper_command="riper_smp",
    directory="calculations/water_pbe",
)

energy = water.get_potential_energy()
forces = water.get_forces()
band_gap = water.calc.get_band_gap()

print(f"Energy: {energy:.8f} eV")
print(f"Band gap: {band_gap:.6f} eV")
print(forces)

When a calculation succeeds, the band gap is also available as:

water.calc.results["band_gap"]
water.info["band_gap"]

That means ASE extXYZ output includes band_gap automatically:

from ase.io import write

write("water.extxyz", water)

Periodic Example: Graphene With SCAN0

from ase.io import read, write
from riper import RIPERCalculator

graphene = read("examples/graphene_scan0.extxyz")

graphene.calc = RIPERCalculator(
    functional="scan0",
    basis="pob-TZVP-rev2",
    auxbasis="universal",
    nkpoints=[15, 15, 1],
    scfconv=8,
    scfiterlimit=100,
    riper_command="riper_smp",
    directory="calculations/graphene_scan0",
)

energy = graphene.get_potential_energy()
forces = graphene.get_forces()

print(f"Energy per atom: {energy / len(graphene):.8f} eV")
print(f"Band gap: {graphene.info['band_gap']:.6f} eV")
print(f"Max force component: {abs(forces).max():.6f} eV/Angstrom")

write("graphene_scan0.extxyz", graphene)

For 2D systems, only the first two entries of nkpoints are written to the RIPER control file. For 1D systems, only the first entry is used.

Geometry Optimization: B3LYP Water

from ase.build import molecule
from ase.io import write
from ase.optimize import LBFGS
from riper import RIPERCalculator

water = molecule("H2O")
water.calc = RIPERCalculator(
    functional="b3-lyp",
    basis="def2-SVP",
    auxbasis="universal",
    scfconv=8,
    scfiterlimit=100,
    riper_command="riper_smp",
    directory="calculations/water_b3lyp_opt",
)

opt = LBFGS(
    water,
    trajectory="calculations/water_b3lyp_opt.traj",
    logfile="calculations/water_b3lyp_opt.log",
)
opt.run(fmax=0.02)

print(f"Final energy: {water.get_potential_energy():.8f} eV")
print(f"Band gap: {water.info['band_gap']:.6f} eV")

write("calculations/water_b3lyp_optimized.extxyz", water)

1D Periodic Example: LiH Chain

from ase import Atoms
from riper import RIPERCalculator

a = 3.2
lih = Atoms(
    symbols="LiH",
    positions=[[0.0, 0.0, 0.0], [a / 2, 0.0, 0.0]],
    cell=[[a, 0.0, 0.0], [0.0, 20.0, 0.0], [0.0, 0.0, 20.0]],
    pbc=[True, False, False],
)

lih.calc = RIPERCalculator(
    functional="pbe",
    basis="pob-DZVP-rev2",
    auxbasis="universal",
    nkpoints=[8, 1, 1],
    riper_command="riper_smp",
    directory="calculations/lih_chain",
)

print(f"Energy: {lih.get_potential_energy():.8f} eV")
print(f"Band gap: {lih.info['band_gap']:.6f} eV")

Stress Example: Bulk Silicon

from ase.build import bulk
from riper import RIPERCalculator

si = bulk("Si", "diamond", a=5.43)
si.calc = RIPERCalculator(
    functional="pbe",
    basis="pob-DZVP-rev2",
    auxbasis="universal",
    nkpoints=[4, 4, 4],
    calculate_stress=True,
    riper_command="riper_smp",
    directory="calculations/si_stress",
)

energy = si.get_potential_energy()
stress = si.get_stress()

print(f"Energy: {energy:.8f} eV")
print("Stress in ASE Voigt order [xx, yy, zz, yz, xz, xy]:")
print(stress)

Stress parsing uses the RIPER stress tensor, raw: output, divides by the cell volume, and returns ASE Voigt order in eV/Angstrom^3.

D3 Dispersion Example

from ase import Atoms
from riper import RIPERCalculator

water_dimer = Atoms(
    symbols="OHHOHH",
    positions=[
        [0.000, 0.000, 0.117],
        [0.000, 0.757, -0.469],
        [0.000, -0.757, -0.469],
        [2.900, 0.000, 0.117],
        [2.900, 0.757, -0.469],
        [2.900, -0.757, -0.469],
    ],
)

water_dimer.calc = RIPERCalculator(
    functional="pbe",
    basis="def2-SVP",
    auxbasis="universal",
    disp3=True,
    riper_command="riper_smp",
    directory="calculations/water_dimer_d3",
)

print(f"D3 energy: {water_dimer.get_potential_energy():.8f} eV")

Density Cube Example

from ase.build import molecule
from riper import RIPERCalculator

water = molecule("H2O")
water.calc = RIPERCalculator(
    functional="pbe",
    basis="def2-SVP",
    auxbasis="universal",
    plot_dens=True,
    riper_command="riper_smp",
    directory="calculations/water_density",
)

water.get_potential_energy()
print("Density cube written by RIPER as calculations/water_density/td.cub")

plot_dens=True writes:

$pointvalper fmt=cub
   dens

into the control file.

Dipole Moment Example

Use dipole=True to request RIPER electric dipole output during the same SCF run as the energy and forces. The result is available through ASE:

from ase.build import molecule
from riper import RIPERCalculator

water = molecule("H2O")
water.calc = RIPERCalculator(
    functional="pbe",
    basis="def2-SVP",
    auxbasis="universal",
    dipole=True,
    riper_command="riper_smp",
    directory="calculations/water_dipole",
)

water.get_potential_energy()
dipole = water.get_dipole_moment()
print(dipole)  # e*Angstrom

The calculator stores the vector in calc.results["dipole"] for ASE and mirrors it as atoms.info["dipole_moment"] for metadata/trajectory inspection. See examples/example14_0D_water_dipole_geom_opt.py for a before/after geometry optimization example that also converts the trajectory to extXYZ.

UKS and Fixed Unpaired Electrons: Fe desnue Scan

RIPER-specific keywords can be passed through extra_keywords. For example, desnue fixes the target number of unpaired electrons per unit cell when used with UKS and smearing.

from ase.io import read
from riper import RIPERCalculator

fe0 = read("examples/Fe_primitive.cif")

for desnue in [0.0, 1.0, 2.0, 3.0, 4.0]:
    fe = fe0.copy()
    fe.calc = RIPERCalculator(
        functional="pbe",
        basis="pob-DZVP-rev2",
        auxbasis="universal",
        nkpoints=[18, 18, 18],
        uks=True,
        smear=True,
        sigma=0.001,
        scfconv=8,
        scfiterlimit=200,
        extra_keywords={"desnue": f"{desnue:g}"},
        riper_command="riper_smp",
        directory=f"calculations/fe_desnue_{desnue:g}",
    )
    energy = fe.get_potential_energy()
    print(f"desnue={desnue:3.1f}  energy={energy:.8f} eV")

Interlayer Scan Example: Graphene/hBN

The examples directory contains a manual graphene/hBN interlayer-spacing scan. It shifts the hBN layer, computes a potential-energy curve, writes an extXYZ trajectory, and saves a PNG plot.

cd examples
python3 example13_graphene_hbn_interlayer_scan_scan0_disp3.py

Climbing-Image NEB Example

Because RIPERCalculator is a normal ASE calculator, it can be used in ASE NEB workflows. Each image should use a separate calculation directory.

from ase.mep.neb import NEB
from ase.optimize import BFGS
from riper import RIPERCalculator

# images = [reactant, image1, image2, ..., product]
neb = NEB(images, climb=True)
neb.interpolate("idpp")

for i, image in enumerate(images):
    image.calc = RIPERCalculator(
        functional="pbe",
        basis="def2-SVP",
        auxbasis="universal",
        riper_command="riper_smp",
        directory=f"calculations/neb_image_{i:02d}",
    )

opt = BFGS(neb, trajectory="calculations/neb.traj")
opt.run(fmax=0.05)

See examples/example09_neb_ethane_torsional_barrier_staggerd_eclipsed.py for a complete ethane torsional-barrier example.

Calculator Parameters

RIPERCalculator(
    basis=None,
    auxbasis="universal",
    functional="pbe",
    nkpoints=None,
    charge=0,
    uks=False,
    smear=False,
    sigma=0.01,
    riper_command="riper",
    directory=".",
    extra_keywords=None,
    convergence_check="error",
    scfiterlimit=50,
    scfconv=7,
    denconv=None,
    ricore=5000,
    ncore=None,
    disp3=False,
    plot_dens=False,
    dipole=False,
)

Common Options

Option Type / units Meaning
basis str or None Orbital basis. If None, defaults to def2-SVP for 0D and pob-DZVP-rev2 for periodic systems.
auxbasis str Auxiliary basis, default universal. Written as jbas in $atoms.
functional str TURBOMOLE functional keyword, for example pbe, b3-lyp, scan0. Written under $dft.
nkpoints list of int Monkhorst-Pack style RIPER k-point counts. Only periodic directions are written: first 1 entry for 1D, first 2 for 2D, first 3 for 3D.
charge int, electrons Total system charge. Nonzero values write an $atomdens charge block.
uks bool Enables unrestricted Kohn-Sham by writing $uhf.
smear bool Enables Gaussian smearing by writing sigma inside $riper.
sigma float, Hartree Gaussian smearing width. This is a RIPER energy in Hartree, not eV.
extra_keywords dict[str, str] Additional key/value entries written inside $riper, for example {"desnue": "4"}. Values are passed through as text.
scfiterlimit int, cycles Writes $scfiterlimit, the maximum number of SCF iterations.
scfconv int, Hartree exponent Writes $scfconv N, meaning an SCF energy convergence threshold of about 10^-N Hartree. For example scfconv=8 means 1e-8 Ha, not eV.
denconv str or None, RIPER/TURBOMOLE notation Optional $denconv value, for example "1.0d-7". This is passed through exactly.
ricore int, float, or None, MB Writes $ricore <value> to control memory for holding RI integrals in memory. Default is 5000 MB. Use None to omit the keyword.
ncore int or None, threads If None, no thread-count environment variables are set. If set, the RIPER subprocess receives PARNODES, OMP_NUM_THREADS, MKL_NUM_THREADS, OPENBLAS_NUM_THREADS, and NUMEXPR_NUM_THREADS; on macOS it also receives VECLIB_MAXIMUM_THREADS and ACCELERATE_MAXIMUM_THREADS.
disp3 bool Adds $disp3 for DFT-D3 dispersion correction.
plot_dens bool Requests density cube output by writing $pointvalper fmt=cub and dens. RIPER writes td.cub.
dipole bool Requests SCF electric dipole output by writing $fields / electric on. Parsed from RIPER a.u. and returned as an ASE dipole vector in e*Angstrom.
convergence_check str enum One of "error", "warning", or "ignore"; controls how detected RIPER non-convergence is handled.
riper_command str, shell command Command executed in the calculation directory, for example riper, riper_smp, riper_omp, or a full path.
directory str path Working directory where coord, control, riper.out, and other RIPER files are written.

Calculator outputs use ASE units: energy in eV, forces in eV/Angstrom, stress in eV/Angstrom^3, and band gap in eV. Input convergence and smearing options follow TURBOMOLE/RIPER conventions, so energy thresholds such as scfconv and sigma are in Hartree.

RI Memory and Core Count

RIPER can use $ricore to control the memory available for holding RI integrals in memory. The calculator argument is in MB and defaults to 5000:

from riper import RIPERCalculator

calc = RIPERCalculator(
    functional="pbe",
    basis="pob-DZVP-rev2",
    ricore=50000,  # MB
    riper_command="riper_smp",
)

This writes:

$ricore 50000

to the TURBOMOLE control file.

RIPER is an SMP/OpenMP parallel TURBOMOLE module. TURBOMOLE workflows often set thread counts outside Python with variables such as PARNODES and OMP_NUM_THREADS. By default, RIPERCalculator(ncore=None) does not change any environment variables and simply inherits the current shell environment.

If you want the calculator to set the thread count only for the RIPER subprocess, use ncore:

calc = RIPERCalculator(
    functional="pbe",
    basis="pob-DZVP-rev2",
    ricore=50000,  # MB
    ncore=32,      # subprocess threads
    riper_command="riper_smp",
)

When ncore=32, the subprocess receives PARNODES=32, OMP_NUM_THREADS=32, MKL_NUM_THREADS=32, OPENBLAS_NUM_THREADS=32, and NUMEXPR_NUM_THREADS=32. On macOS it also receives VECLIB_MAXIMUM_THREADS=32 and ACCELERATE_MAXIMUM_THREADS=32. The calculator does not mutate os.environ globally.

Files Written

For each calculation directory, the calculator writes at least:

  • coord: TURBOMOLE coordinates in Bohr.
  • control: TURBOMOLE control file.
  • riper.out: RIPER stdout/stderr.

RIPER/TURBOMOLE may also create files such as statistics, ddens, errvec, oldfock, td.cub, EIGS, and updated gradient data in control.

Band Gap

After a successful calculation, call:

gap = atoms.calc.get_band_gap()

The value is parsed from the final RIPER output block:

---------------- Fermi Level Statistics (eV) ----------------
    Lowest unoccupied band = ...
    Highest occupied band  = ...
    Band gap               = ...
    Band gap middle        = ...
    Fermi level            = ...
-------------------------------------------------------------

The parsed gap is stored in eV.

Included Examples

The repository includes these scripts:

  • examples/example01_0D_water.py: water single-point energy and forces.
  • examples/example02_0D_water_geom_opt.py: water geometry optimization.
  • examples/example03_1D_LiH.py: 1D LiH chain and lattice scan.
  • examples/example04_adjust_conv_criteria.py: tighter SCF and density convergence.
  • examples/example05_dispersion_correction.py: D3 dispersion correction.
  • examples/example06_gen_density_cube.py: density cube output.
  • examples/example07_calculate_stress.py: stress tensor for bulk silicon.
  • examples/example08_bulk_Si_unit_cell+geom_opt.py: cell and geometry optimization.
  • examples/example09_neb_ethane_torsional_barrier_staggerd_eclipsed.py: CI-NEB ethane rotation.
  • examples/example10_0D_water_b3lyp_geom_opt.py: B3LYP water optimization.
  • examples/example11_graphene_scan0.py: graphene with SCAN0 and pob-TZVP-rev2.
  • examples/example12_Fe_desnue_scan.py: UKS Fe desnue scan.
  • examples/example13_graphene_hbn_interlayer_scan_scan0_disp3.py: graphene/hBN interlayer scan.
  • examples/example14_0D_water_dipole_geom_opt.py: water dipole before and after optimization.
  • examples/example15_graphene_ricore_ncore.py: 3x3x1 graphene supercell showing ricore and ncore.
  • examples/example16_0D_water_scan0_vibrations.py: SCAN0 water optimization and vibrational modes.
  • examples/example17_bulk_Si_pbe_hse06_band_gap.py: silicon unit-cell band gaps from PBE and HSE06.
  • examples/example18_graphene_phonon_band_structure.py: graphene phonon band structure along Gamma-M-K-Gamma.

Notes and Limitations

  • Periodicity is inferred from atoms.pbc by counting periodic axes.
  • The current lattice writer assumes leading periodic directions: x for 1D, x/y for 2D, x/y/z for 3D.
  • riper_command is executed in the selected calculation directory.
  • Forces are read from the $grad block in the updated control file.
  • Stress requires periodic systems and RIPER output containing stress tensor, raw:.
  • extra_keywords are written inside the $riper section as simple key value lines.

Contact

Manas Sharma

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

riper-0.2.9.tar.gz (36.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

riper-0.2.9-py3-none-any.whl (18.5 kB view details)

Uploaded Python 3

File details

Details for the file riper-0.2.9.tar.gz.

File metadata

  • Download URL: riper-0.2.9.tar.gz
  • Upload date:
  • Size: 36.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for riper-0.2.9.tar.gz
Algorithm Hash digest
SHA256 2567c55392e64e7ebdd944242d473aa8ab5d07065dbfc4adb62873a82192d5bb
MD5 cb31e1f791d791efff46389661471173
BLAKE2b-256 70868a42fdf383aa34cc94b6c4ac56b8310da64e9fcde856f3d2a779e1540878

See more details on using hashes here.

File details

Details for the file riper-0.2.9-py3-none-any.whl.

File metadata

  • Download URL: riper-0.2.9-py3-none-any.whl
  • Upload date:
  • Size: 18.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"22.04","id":"jammy","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for riper-0.2.9-py3-none-any.whl
Algorithm Hash digest
SHA256 e56bf8e2f872b31a6e539a2687d65d698e7dd7c904e102e350e2e3164e3bde24
MD5 1121b58c9a9774f184c3cd96f59b9d6b
BLAKE2b-256 423bef8241051954d107886f8c725a318606a72ea2fa16e9ad6a93da8185f67e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page