User guide¶
This guide goes a bit deeper than Getting started. It covers the
geometric primitives available for insertion, the trade-off between the
Insert* and Solvate* family, the built-in water models, and the
knobs you can turn when a difficult system refuses to pack.
Insertion regions¶
solvate provides three insertion regions. All of them accept the same
target, projectile, and n arguments and differ only in the
shape of the volume they fill.
Rectangular boxes¶
InsertPlanar() fills an axis-aligned box. By default the
box is the full simulation cell of the target; use xmin/xmax,
ymin/ymax, zmin/zmax to carve out a sub-region — for example a
solvent slab on top of a surface:
# Insert water only between z = 20 Å and z = 40 Å
slab = solvate.InsertPlanar(
surface, solvate.models.spce(), n=500, zmin=20.0, zmax=40.0,
)
Cylinders¶
InsertCylinder() fills a cylinder. dim selects the axis
(0 = x, 1 = y, 2 = z; default dim=2), radius controls the cross
section, and min/max are the lower and upper bounds along the cylinder
axis. pos sets the cylinder centre; when omitted it falls on the centre
of geometry of the target (or the centre of the box for an empty target).
# Fill a pore of radius 8 Å aligned with z, between z = 0 and z = 50 Å
pore = solvate.InsertCylinder(
target, solvate.models.spce(), n=200, radius=8.0, max=50.0,
)
Spheres¶
InsertSphere() fills a sphere centred at pos (default:
target centre of geometry / box centre) with the given radius.
# Build a 20 Å water droplet
droplet = solvate.InsertSphere(
box, solvate.models.spce(), n=1000, radius=20.0,
)
Insert* versus Solvate*¶
The Insert* functions place projectiles one by one and re-check for
overlaps with every new candidate. They are the right choice for small
numbers of insertions (a few hundred at most) or when you need full control
over the placement order.
The Solvate* family — currently SolvatePlanar() and
SolvateCylinder() — uses a much faster strategy:
Pack a small “seed” patch of solvent until it is saturated.
Tile that patch across the target region.
Remove projectiles that clash with the target in a single batched neighbour search.
This is the recommended approach whenever you want to solvate a target
with many thousands of solvent molecules. It is also the way to specify a
density instead of an explicit n.
Built-in water models¶
The solvate.models module gives you ready-to-use water models as
MDAnalysis Universes:
Function |
Model |
Notes |
|---|---|---|
SPC/E |
3-site, θ = 109.47° |
|
TIP3P |
3-site, θ = 104.52° |
|
TIP4P/ε |
4-site (extra massless M site) |
Need a custom 3- or 4-site model? Build it directly with
type_a() (3-site) or type_c()
(4-site), passing your bond length, partial charges, and HOH angle.
import numpy as np
import solvate
# A toy 3-site model with a 100° HOH angle
custom = solvate.models.type_a(
l_1=1.0, q_O=-0.8, q_H=0.4, theta=np.deg2rad(100.0),
)
To start from a truly empty system (no atoms, just box dimensions), use
empty().
Tuning the solver¶
When the target is densely packed, or when you ask for many projectiles in a small region, placement can become difficult. A few knobs help:
distance(default1.25Å)Minimum distance between a projectile and any existing atom. Lowering it allows tighter packing at the risk of unphysical contacts.
tries(default1000)Maximum random placement attempts per projectile before
InsertPlanar()(or its siblings) raises aRuntimeError. Increase it when packing is tight.fudge_factor(Solvate*only, default1.0)Multiplier applied to the seed-patch population. The
Solvate*functions automatically increase it and retry when not enough projectiles survived the overlap pruning, so you rarely need to set it by hand.densityversusnPass
density(in molecules / ų) to let solvate compute the number of projectiles from the volume of the insertion region. Passnwhen you need an exact molecule count.
Tips and gotchas¶
Set the simulation cell before inserting. Random positions are drawn from the cell dimensions, so a missing or zero-sized box leads to surprising results. Use
solvate.models.empty()to construct an empty Universe with a well-defined box.Prefer ``Solvate*`` for large boxes. A 50 × 50 × 50 ų water box with
InsertPlanar()will take a long time;SolvatePlanar()does it in seconds.Write whatever format you need. The returned object is a regular MDAnalysis Universe —
universe.atoms.write("foo.gro"),"foo.xyz","foo.pdb"all work.