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.
ExTinyMD.CubicBoundary — Function
CubicBoundary(L)A Boundary that is a cube of side L, periodic in all three axes.
ExTinyMD.Q2dBoundary — Function
Q2dBoundary(Lx, Ly, Lz)A Boundary periodic in x and y, free in z — a quasi-2D slab of in-plane size Lx × Ly and z-extent Lz.
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).
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.
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.
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.
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}}.
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.
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.
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.
ExTinyMD.position_checkQ2D — Function
position_checkQ2D(coord_1, coord_2, boundary, cutoff) -> (image_1, image_2, dist_sq)Like position_check3D, but only x and y are searched for periodic images; z is treated as free.
ExTinyMD.dist2 — Function
dist2(x, y) -> Number
dist2(x) -> NumberSquared Euclidean distance between x and y (numbers or Points), or the squared norm of x alone.
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]).
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.
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.
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).
Thermostats
ExTinyMD.NoThermoStat — Type
NoThermoStat()A thermostat that does nothing, i.e. NVE (microcanonical) dynamics.
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.
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 ν.
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.
Loggers
Loggers are attached to MDSys via the loggers keyword and run once per step inside simulate!.
ExTinyMD.TemperatureLogger — Type
TemperatureLogger{T, TI} <: AbstractLoggerRecords 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)ExTinyMD.TrajectoryLogger — Type
TrajectoryLogger{TI} <: AbstractLoggerRecords 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)ExTinyMD.EnergyLogger — Type
EnergyLogger{TI} <: AbstractLoggerRecords 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.
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.update_finder! — Function
update_finder!(neighborfinder, info)Refresh neighborfinder's neighbour list from the current positions in info, typically every update_steps steps. Every concrete AbstractNeighborFinder implements a method; NoNeighborFinder and AllNeighborFinder are no-ops.
ExTinyMD.NoNeighborFinder — Type
NoNeighborFinder(T = Float64)A neighbor finder with an always-empty list, for interactions such as ExternalField that need no pairwise neighbours at all.
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.
ExTinyMD.CellList3D — Type
CellList3D{T, TI, NL} <: AbstractNeighborFinderA 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.
ExTinyMD.CellListDir3D — Type
CellListDir3D{T, TI} <: AbstractNeighborFinderA 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)ExTinyMD.CellListQ2D — Type
CellListQ2D{T, TI, NL} <: AbstractNeighborFinderLike CellList3D, but the neighbour search is only in x and y (z is ignored), for quasi-2D slabs.
CellListQ2D(info, cutoff, boundary, update_steps)ExTinyMD.CellListDirQ2D — Type
CellListDirQ2D{T, TI} <: AbstractNeighborFinderLike CellListDir3D, but the neighbour search is only in x and y, for quasi-2D slabs.
CellListDirQ2D(info, cutoff, boundary, update_steps)ExTinyMD.SubNeighborFinder — Type
SubNeighborFinder{T, TI} <: AbstractNeighborFinderTracks 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)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].
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.
ExTinyMD.data2info — Function
data2info(data::Vector, boundary, masses, charges) -> (atoms, info)Build atoms and a SimulationInfo from one frame of data (as returned by load_trajectory or load_lammpstrj), looking up each particle's mass and charge in masses/charges by its type.
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.
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.
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.
ExTinyMD.MSD — Function
MSD(data::Vector, boundary; s::Int64 = 1) -> msdMean 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}.