Targets¶
A Target describes one type of molecule to pack: its template
geometry, element symbols, and the number of copies to produce.
VdW radii are resolved automatically from element symbols via the
Bondi (1964) table.
Construction¶
frame— amolrs.Frameormolpy.Frame, resolved zero-copy via its FFI capsule. Supported sources:
| Source | Element column |
|---|---|
molrs.read_pdb(path) |
"symbol" |
molrs.read_xyz(path) |
"element" |
molrs.Frame.from_dict({"blocks": {"atoms": {...}}}) |
"element" |
molpy.Frame |
"element" |
count— number of copies to produce.
A display label is optional:
Build a frame in memory (no PDB file) with molrs.Frame.from_dict:
import molrs
import numpy as np
frame = molrs.Frame.from_dict({
"blocks": {
"atoms": {
"x": np.array([0.00, 0.96, -0.24]),
"y": np.array([0.00, 0.00, 0.93]),
"z": np.zeros(3),
"element": ["O", "H", "H"],
}
}
})
water = Target(frame, count=100).with_name("water")
Read-only properties¶
target.name # Optional[str]
target.natoms # number of template atoms
target.count # requested copies
target.elements # list[str]
target.radii # list[float]
target.is_fixed # True if placement is frozen (see below)
All builder methods are immutable — they return a new Target.
Centering¶
The default is CenteringMode.AUTO — free
targets are centered on their geometric center before packing; fixed
targets are kept in place. Override explicitly:
from molpack import CenteringMode
target = target.with_centering(CenteringMode.CENTER) # always center
target = target.with_centering(CenteringMode.OFF) # keep input coords
Fixed placement¶
Pin a target at a specific location (e.g. a fixed reference molecule):
from molpack import Angle
target = target.fixed_at([10.0, 20.0, 30.0])
# optional Euler orientation — three Angle values in Packmol's
# eulerfixed convention
target = (
target.fixed_at([10.0, 20.0, 30.0])
.with_orientation((
Angle.from_degrees(0.0),
Angle.from_radians(1.57),
Angle.ZERO,
))
)
Fixed targets are excluded from the optimizer but still contribute to distance exclusion against other species.
Rotation bounds¶
Restrict the rotational search window about each axis:
from molpack import Angle, Axis
target = (
target
.with_rotation_bound(Axis.X, Angle.from_degrees(0.0), Angle.from_degrees(15.0))
.with_rotation_bound(Axis.Y, Angle.from_degrees(90.0), Angle.from_degrees(10.0))
.with_rotation_bound(Axis.Z, Angle.from_degrees(0.0), Angle.from_degrees(5.0))
)
Angle makes units explicit: use Angle.from_degrees(...) or
Angle.from_radians(...) — raw floats are rejected.
Attaching restraints¶
All atoms of the target¶
from molpack import InsideBoxRestraint
target = target.with_restraint(
InsideBoxRestraint([0, 0, 0], [40, 40, 40])
)
Stack multiple restraints by calling .with_restraint() again:
target = (
target
.with_restraint(InsideBoxRestraint([0, 0, 0], [40, 40, 40]))
.with_restraint(OutsideSphereRestraint([20, 20, 20], 5.0))
)
A subset of atoms¶
from molpack import AbovePlaneRestraint, BelowPlaneRestraint
target = target.with_atom_restraint(
[30, 31], # 0-based Rust-native indices
BelowPlaneRestraint([0.0, 0.0, 1.0], 2.0),
)
0-based indexing
with_atom_restraint uses 0-based indices, matching Rust
convention. If you are porting from a Packmol .inp file (which
uses 1-based indices), subtract 1 at the call site.
Relaxation-assisted packing¶
Attach an in-loop relaxer to reshape a flexible molecule's reference
geometry during packing — useful for long chains that must fold to
fit. with_relaxer requires count == 1 (every copy shares the
reference geometry the relaxer rewrites):
from molpack import Target, TorsionMcRelaxer
chain = TorsionMcRelaxer(frame).with_steps(20).with_self_avoidance(1.5)
target = Target(frame, count=1).with_relaxer(chain)
Two relaxers ship built in: TorsionMcRelaxer (engine-free Monte-Carlo
torsion sampling, always available) and LBFGSRelaxer (force-field
L-BFGS, ff feature). See
In-loop relaxers for their
options.
Per-target solver budget¶
Override the maximum perturbation budget for this target:
Useful when one species is significantly harder to place than the rest.