Electrostatic Potential (ESP) Maps
The electrostatic potential (ESP) describes the electric potential energy a unit positive test charge would experience at each point in space around a molecule. sci-form generates ESP maps on 3D voxel grids.
ESP Grid Generation
Coulomb Potential Formula
At each grid point
where:
= partial charge on atom (from population analysis) = position of atom = distance from the grid point to atom
Grid Construction
The 3D grid is built from the molecular bounding box:
- Bounding box: Find min/max atomic coordinates along each axis
- Padding: Extend by a padding distance (default 3.0 Å) in all directions
- Spacing: Place grid points at regular intervals (default 0.5 Å)
- Dimensions:
grid points
ESP Data Structure
pub struct EspGrid {
pub origin: [f64; 3], // grid corner
pub spacing: f64, // grid spacing in Å
pub dims: [usize; 3], // (Nx, Ny, Nz)
pub values: Vec<f64>, // Nx × Ny × Nz ESP values
pub elements: Vec<u8>, // atomic numbers
pub positions: Vec<[f64; 3]>, // atom positions
}Parallel Grid Evaluation
The full 3D grid can involve millions of points. sci-form evaluates grid points in parallel using Rayon when the parallel feature is enabled:
// Serial (default)
let grid = compute_esp_grid(&mol, 0.5, 3.0);
// Parallel (requires feature = "parallel")
let grid = compute_esp_grid_parallel(&mol, 0.5, 3.0);The parallel version partitions grid points into chunks across all available threads, giving near-linear speedup on multi-core systems.
Color Mapping
ESP values are mapped to an RGB color scale using esp_color_map(value, range):
where
| ESP Value | Color | Chemical Meaning |
|---|---|---|
| Deep red | Strongly electron-rich, nucleophilic site | |
| Light red → white | Mildly electron-rich | |
| White | Neutral region | |
| Light blue → white | Mildly electron-poor | |
| Deep blue | Strongly electron-poor, electrophilic site |
The full grid can be converted to an RGB byte array:
use sci_form::esp::{esp_grid_to_colors};
let colors = esp_grid_to_colors(&grid, 0.05); // range = 0.05 a.u.
// returns Vec<u8> of length 3 × Nx × Ny × Nz (r,g,b per point)Gaussian Cube Format
sci-form supports import/export of the .cube file format for interoperability with Gaussian, PySCF, and visualization tools.
Cube File Structure
Title line 1
Title line 2
N_atoms origin_x origin_y origin_z
N_x dx_x dx_y dx_z
N_y dy_x dy_y dy_z
N_z dz_x dz_y dz_z
Z_1 charge_1 x_1 y_1 z_1
...
value_1 value_2 value_3 ... (Nx × Ny × Nz float values)Units in cube files are Bohr (1 Bohr = 0.529177 Å).
API
Rust
use sci_form::compute_esp;
let grid = compute_esp("O", 0.5, 3.0, None);
// grid.values: Vec<f64> — ESP at each grid point
// grid.dims: [usize; 3] — grid dimensions
// grid.to_cube() -> String — export as .cube formatCLI
sci-form esp "O" --spacing 0.5 --padding 3.0
# Output: JSON with grid metadata and valuesPython
import sci_form
grid = sci_form.esp("O", spacing=0.5, padding=3.0)
print(grid.dims) # (Nx, Ny, Nz)
print(len(grid.values)) # Nx * Ny * Nz
cube_str = grid.to_cube()Validation
- Consistency:
= len(values) - Finiteness: All ESP values are finite (no infinities or NaN)
- Polarity: Polar molecules have both positive and negative ESP regions
- Cube roundtrip: Export to
.cubeand re-import produces identical grid - Resolution: Finer spacing produces more grid points