MD Core

This page covers the pieces used to build and drive an ordinary (non-electrostatic) molecular dynamics simulation: the box, the atoms, the simulation state, the integrators and thermostats, the loggers, and the neighbour finders. See Interactions for how forces get added to the system, and Electrostatics for the electrostatics standard library.

Box and atoms

A simulation lives in a Boundary box populated with Atoms. CubicBoundary and Q2dBoundary build the two shapes used throughout this package: a fully periodic cube, and a slab periodic in x and y only.

ExTinyMD.Boundary — Type
Boundary{T}(length, period)

The simulation box: length is the (Lx, Ly, Lz) edge lengths and period is (px, py, pz) with 1 for a periodic axis and 0 for a free (non-periodic) axis. See also CubicBoundary and Q2dBoundary for common cases, and the Boundary(L, ('p','p','f'))-style constructor in boundary.jl.

source
ExTinyMD.Atom — Type
Atom{T}(type, mass, charge)

A particle species: an integer type tag, a mass, and a charge. Construct with keywords: Atom(type = 1, mass = 1.0, charge = 0.0).

source
ExTinyMD.create_atoms — Function
create_atoms(atoms_types::Vector{Tuple{Int, Atom{T}}}) -> Vector{Atom{T}}

Expand [(count_1, atom_1), (count_2, atom_2), ...] into a flat vector containing count_1 copies of atom_1, then count_2 copies of atom_2, and so on.

source

Simulation state

SimulationInfo holds the mutable state — positions, velocities, accelerations, and the running step count — while MDSys bundles the (immutable, for the run) description of the system: the atoms, the box, the interactions, the loggers, and the simulator.

ExTinyMD.SimulationInfo — Type
SimulationInfo{T}

Mutable simulation state: the current running_step, a Vector of per-particle (id, position, velocity, acceleration) records in storage-slot order, and id_dict mapping a particle id to its current slot. Also constructible as SimulationInfo(n_atoms, atoms, place, boundary; min_r, max_attempts, rng, temp), which randomly places n_atoms atoms inside the box place = (xlo, xhi, ylo, yhi, zlo, zhi) and draws velocities from a Maxwell-Boltzmann distribution at temperature temp.

source
ExTinyMD.random_position — Function
random_position(n_atoms, place, boundary; min_r = 0, max_attempts = 100)

Randomly place n_atoms points inside the box place = (xlo, xhi, ylo, yhi, zlo, zhi). When min_r > 0, each new point is rejected and retried (respecting boundary's periodic images) until it is at least min_r from every existing point, giving up after max_attempts consecutive failures. Returns a Vector{Point{3,T}}. 3D only.

source
ExTinyMD.random_velocity — Function
random_velocity(; temp, atoms, rng = Random.GLOBAL_RNG)

Draw a Maxwell-Boltzmann velocity for each atom in atoms at temperature temp (per-component standard deviation sqrt(temp / mass)). Returns a Vector{Point{3,T}}.

source
ExTinyMD.MDSys — Type
MDSys(; n_atoms, atoms, boundary, interactions, loggers, simulator)

The top-level MD system: the atoms, the box, a list of (interaction, neighbor_finder) pairs, the loggers to run each step, and the simulator driving the integration. Passed to simulate! together with a SimulationInfo.

source
ExTinyMD.BoundaryCheck! — Function
BoundaryCheck!(simulation_info, boundary)

Wrap every particle position in simulation_info back into the primary box along each periodic axis of boundary, leaving free axes untouched.

source
ExTinyMD.position_check3D — Function
position_check3D(coord_1, coord_2, boundary, cutoff) -> (image_1, image_2, dist_sq)

Search the periodic images of coord_1 (in all three axes per boundary) for one within cutoff of coord_2, returning that image pair and their squared distance, or a zeroed triple if none is found. Accepts either Point or NTuple{3} coordinates.

source
ExTinyMD.dist2 — Function
dist2(x, y) -> Number
dist2(x) -> Number

Squared Euclidean distance between x and y (numbers or Points), or the squared norm of x alone.

source
ExTinyMD.Point — Type
Point{N,T}(coo::NTuple{N,T})

A small fixed-size vector of N coordinates of type T, used throughout ExTinyMD for positions, velocities, accelerations, and the electric field. Supports +, -, scalar *//, iteration, and indexing (p[i]).

source

Running a simulation

ExTinyMD.simulate! — Function
simulate!(simulator, sys, info, total_steps)

Run total_steps integration steps of simulator on sys/info, invoking record! on every logger in sys.loggers after each step. Mutates info in place; returns nothing.

source
ExTinyMD.VerletProcess — Type
VerletProcess(; dt, thermostat = NoThermoStat())

Velocity-Verlet integrator with time step dt and an optional thermostat applied once per step after the position/velocity update.

source
ExTinyMD.NHVerletProcess — Type
NHVerletProcess(; dt, Q = 1.0, temperature)

Nose-Hoover chain (length 1) Verlet integrator at target temperature, with time step dt and thermostat mass Q. Implements the Frenkel & Smit (Understanding Molecular Simulation) algorithm; vξ, ξ and Ek are the thermostat's internal state, initialised to zero (Ek on the first step).

source

Thermostats

ExTinyMD.AndersenThermoStat — Type
AndersenThermoStat(temperature, ν)

Andersen thermostat at the given temperature, with collision frequency ν: each step, every particle's velocity is redrawn from the Maxwell-Boltzmann distribution with probability ν * dt.

source
ExTinyMD.BerendsenThermoStat — Type
BerendsenThermoStat(temperature, ν)

Berendsen weak-coupling thermostat at the given temperature, with coupling time ν: every step rescales all velocities by a common factor that relaxes the instantaneous temperature toward temperature with time constant ν.

source
ExTinyMD.thermostat_update! — Function
thermostat_update!(thermostat, sys, info)

Apply one thermostat step, typically rescaling or resampling velocities in info.particle_info. Every concrete AbstractThermoStat implements a method; NoThermoStat is a no-op.

source

Loggers

Loggers are attached to MDSys via the loggers keyword and run once per step inside simulate!.

ExTinyMD.TemperatureLogger — Type
TemperatureLogger{T, TI} <: AbstractLogger

Records the instantaneous temperature every step steps, appending each value to data and, when output = true, to temperature.txt.

TemperatureLogger(step; output = true)
TemperatureLogger{T}(step; output = true)
source
ExTinyMD.TrajectoryLogger — Type
TrajectoryLogger{TI} <: AbstractLogger

Records a full trajectory frame (id, atom_type, x, y, z, vx, vy, vz for every particle) every step steps, appended to trajectory_file when output = true.

TrajectoryLogger(; step, trajectory_file = "trajectory.txt", output = true)
source
ExTinyMD.EnergyLogger — Type
EnergyLogger{TI} <: AbstractLogger

Records kinetic energy and the energy of each of interactions every step steps, writing a CSV-like step, Ek, ... line to energy_file when output = true.

EnergyLogger(step; interactions, energy_names, energy_file = "energy.txt", output = true)

interactions is a Vector of (interaction, neighbor_finder) pairs and energy_names labels them, one name per pair.

source

Neighbour finders

A neighbour finder is paired with each interaction as (interaction, finder) in MDSys's interactions list. update_finder! refreshes it; most interactions call this themselves before using the list.

ExTinyMD.AllNeighborFinder — Type
AllNeighborFinder(n_atoms, T = Float64)

A neighbor finder whose list is every distinct pair (i, j), i < j, with no cutoff and no update logic. Useful for small systems or as a reference when a cutoff-based finder is not needed.

source
ExTinyMD.CellList3D — Type
CellList3D{T, TI, NL} <: AbstractNeighborFinder

A 3D neighbour finder backed by CellListMap.InPlaceNeighborList, rebuilt in place every update_steps steps.

CellList3D(info, cutoff, boundary, update_steps)

Build one from the current positions in info with the given cutoff. A non-periodic axis of boundary has its cell-list unit-cell length inflated so no periodic images are found along it.

source
ExTinyMD.CellListDir3D — Type
CellListDir3D{T, TI} <: AbstractNeighborFinder

A 3D neighbour finder that recomputes the full neighbour list directly (via CellListMap.neighborlist, not an in-place cell list) every update_steps steps. Simpler and more predictable than CellList3D at the cost of reallocating each rebuild.

CellListDir3D(info, cutoff, boundary, update_steps)
source
ExTinyMD.CellListQ2D — Type
CellListQ2D{T, TI, NL} <: AbstractNeighborFinder

Like CellList3D, but the neighbour search is only in x and y (z is ignored), for quasi-2D slabs.

CellListQ2D(info, cutoff, boundary, update_steps)
source
ExTinyMD.CellListDirQ2D — Type
CellListDirQ2D{T, TI} <: AbstractNeighborFinder

Like CellListDir3D, but the neighbour search is only in x and y, for quasi-2D slabs.

CellListDirQ2D(info, cutoff, boundary, update_steps)
source
ExTinyMD.SubNeighborFinder — Type
SubNeighborFinder{T, TI} <: AbstractNeighborFinder

Tracks which particles are within cutoff of two flat substrates at z = sub_down and z = sub_up, for SubLennardJones. Maintains up_neighbor/down_neighbor, the ids close to each wall.

SubNeighborFinder(cutoff, info, sub_down, sub_up; update_steps = 100)
source

Data loading and analysis

ExTinyMD.load_trajectory — Function
load_trajectory(filename::String) -> (trajectory_list, step_list)

Load a trajectory written by TrajectoryLogger from filename. trajectory_list[k] is a vector of [id, type, x, y, z, vx, vy, vz] rows for recorded step step_list[k].

source
ExTinyMD.load_lammpstrj — Function
load_lammpstrj(filename::String) -> (trajectory, box, timestep, num_atoms)

Parse a LAMMPS dump file (ITEM: TIMESTEP / ITEM: NUMBER OF ATOMS / ITEM: BOX BOUNDS pp pp ff / ITEM: ATOMS id type x y z blocks). Returns each frame's (id, type, x, y, z) tuples in trajectory, the box bounds box = (xlo, xhi, ylo, yhi, zlo, zhi), the recorded timesteps, and num_atoms.

source
ExTinyMD.z_hist — Function
z_hist(z, bin, z_min, z_max, Lx, Ly, steps) -> (z_list, density)

Histogram the z-coordinates in z into bin - 1 bins spanning [z_min, z_max], normalised into a number density by the in-plane area Lx * Ly, the bin width, and the number of sampled steps. Returns the bin centres z_list alongside the density.

source
ExTinyMD.hist_init — Function
hist_init(N, bin, r_c) -> (hist, volume, r, dr)

Allocate a zeroed radial histogram of bin bins spanning (0, r_c], together with the bin radii r, bin width dr = r_c / bin, and the spherical-shell volume of each bin (for normalising into a radial distribution function). N is accepted for interface symmetry with the sampling loop but does not affect the allocation.

source
ExTinyMD.distance_hist! — Function
distance_hist!(hist, n_list, d)

Bin the pair distances in neighbour list n_list (as (i, j, r) triples) into hist using bin width d, accumulating in place across calls.

source
ExTinyMD.MSD — Function
MSD(data::Vector, boundary; s::Int64 = 1) -> msd

Mean squared displacement per axis, computed from unwrapped positions built by accumulating minimum-image displacements between consecutive frames of data (each frame in the [id, type, x, y, z, ...] layout used by load_trajectory/load_lammpstrj), starting from frame s. Returns msd[k], a vector over time of the mean squared displacement along axis k ∈ {1,2,3}.

source