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.
  • UKS calculations through uks=True.
  • Gaussian smearing through smear=True and sigma=....
  • 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.

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,
    disp3=False,
    plot_dens=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.
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.
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.

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.

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.8.tar.gz (30.1 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.8-py3-none-any.whl (16.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: riper-0.2.8.tar.gz
  • Upload date:
  • Size: 30.1 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.8.tar.gz
Algorithm Hash digest
SHA256 c9ea39b0de4b50a76b38d198e00511a6f5df1771327e6108886947fe2f63319f
MD5 6ab4c0acbd0670001eaca5b14fe420e0
BLAKE2b-256 c6882a8e41d95599d4368bf82cbb2480b271c17e8f10a089d54bfb1f8e8ee79b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: riper-0.2.8-py3-none-any.whl
  • Upload date:
  • Size: 16.2 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.8-py3-none-any.whl
Algorithm Hash digest
SHA256 ddf08221ceef03b4542a3668c6c0d8d3cf80016720f0471e3e048b017001f4ae
MD5 e66d32b5c655eafe197337e69eee3e99
BLAKE2b-256 4123c48559cb5a11458ae47769ed9221b1c5a65f41e91cde58ae01e8cd1ce462

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