# Use positional restraints **You will learn:** how to add positional restraints to an ACEMD simulation, including ramped (time-varying) and flat-bottom variants. **Prerequisites:** - A working ACEMD input file. - An atom selection that picks the atoms you want to restrain. Selection syntax follows [VMD's atom-selection language](https://www.ks.uiuc.edu/Research/vmd/current/ug/node89.html). See [External forces](../reference/external-forces.md) for the full reference of every option used below. ## Setup Restraints go under the top-level `extforces` key of your `input.yaml` file. Each entry has a `type` and type-specific options. Today the only available type is `positionalRestraint`: ```{code-block} yaml :caption: input.yaml extforces: - type: positionalRestraint sel: "protein and name CA" setpoints: - 1@0 ``` This applies a 1 kcal/mol/Ų harmonic restraint to every protein Cα for the whole simulation. ## Ramp a restraint down during equilibration Restraints are usually held strong at the start and released over the equilibration. Use multiple `setpoints` — values are linearly interpolated between consecutive entries: ```{code-block} yaml :caption: input.yaml extforces: - type: positionalRestraint sel: "protein and name CA" setpoints: - 1@0ns - 0@10ns ``` Time suffixes (`fs`, `ps`, `ns`, `us`) or raw step counts are both accepted. A bare number means **steps**, not nanoseconds — `0@2500000` is "at step 2,500,000", whereas `0@2500000ns` is "at 2.5 ms of simulated time". Prefer the suffixed form to avoid ambiguity. ## Restrain inside a flat-bottom box around a moving centre `fbCenter` with an atom selection makes the restraint follow the **centre of mass** of that selection. Pair it with `fbWidth` to define a tolerance box: ```{code-block} yaml :caption: input.yaml extforces: - type: positionalRestraint sel: "resname MOL" fbwidth: 10 fbcenter: "protein and name CA" setpoints: - 0.5@0 ``` The ligand is free to move within a 10 Å box centred on the protein's Cα COM, and pushed back if it leaves. ## Restrain inside a slab above the membrane A common pattern for membrane-permeation simulations — keep ligands inside a 20 Å slab centred 10 Å above the bilayer: ```{code-block} yaml :caption: input.yaml extforces: - type: positionalRestraint sel: "resname MOL and noh" axes: "z" fbwidth: 20 fbcenter: "(lipid or resname AR CHL DHA LAL MY OL PA PC PE PGR PGS PS SA SPM ST) and noh" fbcenteroffset: [0, 0, 10] setpoints: - 0.5@0 ``` The lipid selection above is the authoritative residue list used by ACEMD's cellular-restraint helper — it is defined once as the constant `LIPIDSEL` in `acemd.protocols`. If you build your own membrane selection, keep it in sync with that source of truth. For the symmetric case (above **and** below the membrane), {py:func}`~acemd.protocols.get_cellular_restraints` builds the YAML for you. ## Restrain only one direction A `+` or `-` prefix on an axis activates the restraint **only when the atom moves in that direction** from its reference position; motion in the opposite direction is unrestrained. With `axes: "+z"` the atom is pulled back if it tries to move in `+z`, but is free to move in `-z`: ```{code-block} yaml :caption: input.yaml extforces: - type: positionalRestraint sel: "resname LIG" axes: "+z" setpoints: - 1@0 ``` Here the ligand can sink to lower z (e.g. through a membrane) but is held back from rising above its starting z. Flip to `axes: "-z"` for the opposite: free upward motion, blocked downward. ## Use a reference PDB instead of the starting coordinates The top-level option `fbRefCoor` reads reference atom positions from a separate PDB. Useful when you want the restraints to pull back toward, say, a crystal pose rather than the equilibrated starting frame: ```{code-block} yaml :caption: input.yaml fbrefcoor: crystal.pdb extforces: - type: positionalRestraint sel: "protein and name CA" setpoints: - 1@0 ``` The reference PDB must match the simulation system atom-for-atom. ## Gotchas - **Exclude hydrogens at `timestep > 2 fs`.** Constrained hydrogens combined with strong harmonic restraints can produce NaN coordinates. Use `and noh` on your selection. - **Restraint mass is in your selection.** If `fbCenter` is an atom selection and the selection is empty, ACEMD raises during setup. Verify the selection picks atoms. ## See also - [External forces reference](../reference/external-forces.md) - {py:func}`~acemd.protocols.get_cellular_restraints`