Restraints and PBC¶
Restraints are soft penalties that guide atoms into allowed regions. They can
be attached to a target, to a subset of atoms on each target copy, or globally
on the engine. Geometry is a molrs Region
— Sphere, Cuboid, Parallelepiped, HalfSpace, Cylinder, Ellipsoid,
Polyhedron, SphereUnion, and their AndRegion / OrRegion / NotRegion
compositions — and molpack's one geometric restraint, RegionRestraint, says
"stay inside it".
Whole-target restraints¶
use std::sync::Arc;
use molpack::{RegionRestraint, Target};
use molrs::core::Cuboid;
use ndarray::array;
let cube = Cuboid::new(array![0.0, 0.0, 0.0], array![40.0, 40.0, 40.0]); // origin, lengths
let target = Target::from_coords(positions, radii, 100)
.with_restraint(RegionRestraint(Arc::new(cube)));
Outside a shape is its complement: NotRegion::new(Arc::new(sphere)).
Collective restraints match an entire species to a distribution profile; see
Concepts.
Atom-subset restraints¶
Atom-subset restraints apply to selected atoms of every copy. Indices are 0-based:
use std::sync::Arc;
use molpack::{RegionRestraint, Target};
use molrs::core::HalfSpace;
// z <= 2: the half-space behind the plane through (0, 0, 2) with normal +z.
let below = HalfSpace::new([0.0, 0.0, 1.0], [0.0, 0.0, 2.0])?;
let target = Target::from_coords(positions, radii, 100)
.with_atom_restraint(&[0, 1], RegionRestraint(Arc::new(below)));
If you are translating from a Packmol .inp atoms ... end atoms block,
subtract 1 from each atom index.
Global restraints¶
Attach a restraint to every target through the engine:
use std::sync::Arc;
use molpack::{GencanPack, PackEngine, RegionRestraint, Target};
use molrs::core::Sphere;
use ndarray::array;
let ball = Sphere::new(array![20.0, 20.0, 20.0], 30.0);
let result = GencanPack::new()
.with_global_restraint(RegionRestraint(Arc::new(ball)))
.run(&[a, b], 200)?;
This is equivalent to cloning the same restraint onto every target before packing.
Periodic boxes¶
Periodic boundary conditions are declared on the engine; a region only confines:
use molpack::{GencanPack, PackEngine};
let engine = GencanPack::new().with_periodic_box([0.0; 3], [30.0; 3], [true; 3]);
Per-axis periodicity is the third argument ([true, true, false] for a slab
open along z). A restraint used with periodic boundaries has to mean the same
thing in every image, and molpack refuses by name — RestraintAcrossPeriodicAxis
— one that does not. Two shapes do: a restraint that confines atoms to a
single image (a box, a sphere, a cell), and one that repeats along the
lattice vector (a HalfSpace whose plane runs parallel to it — the slab case).
A half-space across a periodic axis is refused whichever way it was built, the
.inp grammar's plane or a lifted molrs region. Putting a confining region in
the intersection rescues an open one: Cuboid & HalfSpace is bounded, so it
is usable along every axis. A triclinic cell is declared once, as a wall and as
the lattice, by CellRestraint:
use molpack::{CellRestraint, Target};
let cell = CellRestraint::from_lengths_angles([26.0; 3], [90.0, 90.0, 120.0], [true; 3])?;
let target = Target::from_coords(positions, radii, 100).with_restraint(cell);
Invalid or conflicting boxes return typed PackError variants.