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"]andatoms.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=Trueand ASEatoms.get_dipole_moment(). - UKS calculations through
uks=True. - Gaussian smearing through
smear=Trueandsigma=.... - RI integral memory control through
$ricoreviaricore=...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 andpob-TZVP-rev2.examples/example12_Fe_desnue_scan.py: UKS Fedesnuescan.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 showingricoreandncore.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.pbcby counting periodic axes. - The current lattice writer assumes leading periodic directions: x for 1D, x/y for 2D, x/y/z for 3D.
riper_commandis executed in the selected calculation directory.- Forces are read from the
$gradblock in the updatedcontrolfile. - Stress requires periodic systems and RIPER output containing
stress tensor, raw:. extra_keywordsare written inside the$ripersection as simplekey valuelines.
Contact
Manas Sharma
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2567c55392e64e7ebdd944242d473aa8ab5d07065dbfc4adb62873a82192d5bb
|
|
| MD5 |
cb31e1f791d791efff46389661471173
|
|
| BLAKE2b-256 |
70868a42fdf383aa34cc94b6c4ac56b8310da64e9fcde856f3d2a779e1540878
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e56bf8e2f872b31a6e539a2687d65d698e7dd7c904e102e350e2e3164e3bde24
|
|
| MD5 |
1121b58c9a9774f184c3cd96f59b9d6b
|
|
| BLAKE2b-256 |
423bef8241051954d107886f8c725a318606a72ea2fa16e9ad6a93da8185f67e
|