Crystal Phonons with Tako Script
On this page
tako.phonon(structure, settings) runs the browser’s periodic finite-displacement direct method and resolves to a staged phonon result. Use it for a crystal with a valid periodic cell. The equations, force-constant conditioning, acoustic sum rule, and current Γ-DOS limitation are defined in Crystal Phonons and Lattice Dynamics; this chapter defines the public JavaScript contract.
Signature and validation
const result = await tako.phonon(structure, {
calculator,
properties,
phononSupercell,
phononDisplacementAngstrom,
phononBandPath,
phononBandPointsPerSegment,
});
Construct and validate the calculator before allocating a supercell:
const calculator = tako.calculator.mlip({
levelOfTheory: 'nequix-phono',
});
const check = calculator.validate('phonon', {
properties: ['energy', 'forces'],
});
if (!check.ok) throw new Error(check.reasons.join('\n'));
validate('phonon') checks the operation against the calculator capability profile. It does not establish that the model is accurate for the target material, its strain state, or displaced configurations.
Settings
| Setting | Type | Default | Contract |
|---|---|---|---|
calculator | calculator object | required | Supplies forces for every displaced supercell. |
properties | array | shared level default | energy and forces are retained by normalization; the phonon result is controlled by the operation rather than single-point electronic post-processing. |
phononSupercell | three positive integers | [3,3,3] for nequix-phono; [2,2,2] otherwise | Repeats the standardized primitive cell along its three lattice vectors. Values normalize to positive integers and are capped at 6. |
phononDisplacementAngstrom | positive number | 0.01 | Central finite-displacement amplitude in ångström. |
phononBandPath | string | '' | Custom special-point path in the standardized primitive reciprocal basis. Empty requests the SeekPath recommendation during the band stage. |
phononBandPointsPerSegment | positive integer | 16 | Points per path segment, capped at 64. It changes reciprocal interpolation, not force constants. |
The current public call does not expose the lower-level library’s force method, ASR iterations, real-space cutoff, symmetry-reduced displacements, NAC data, q-mesh DOS, or restart caches. The operation always uses central differences, Frederiksen force correction, three symmetry/ASR iterations, and no explicit cutoff. Periodic SeekPath standardization reconstructs the primitive atoms without copying input constraints or custom isotope masses; all reconstructed primitive atoms are active with default elemental masses.
Guard a periodic calculation
const input = await tako.input('input/relaxed-silicon.extxyz');
const calculator = tako.calculator.mlip({
levelOfTheory: 'nequix-phono',
});
const validation = calculator.validate('phonon', {
properties: ['energy', 'forces'],
});
if (!validation.ok) throw new Error(validation.reasons.join('\n'));
const result = await tako.phonon(input, {
calculator,
properties: ['energy', 'forces'],
phononSupercell: [3, 3, 3],
phononDisplacementAngstrom: 0.01,
phononBandPath: '',
phononBandPointsPerSegment: 24,
});
if (result.kind !== 'phonon') {
throw new Error(`Unexpected result kind: ${result.kind}`);
}
if (!result.phonon?.frequencies_cm_inv?.length) {
throw new Error('No Gamma phonon frequencies were returned.');
}
if (!result.phonon_band) {
throw new Error('The requested phonon band was not produced; inspect the path log.');
}
await tako.output('output/phonon-result.json', result);
The call can resolve without phonon_band when SeekPath/path construction or band evaluation fails after Γ data has been emitted. Treat band availability as an explicit requirement only when the script needs it. The current Γ histogram is normally present after a successful periodic finite-displacement stage, but it is not a q-mesh DOS.
Periodic and nonperiodic result branches
A periodic successful result has this top-level shape:
result
├── kind = "phonon"
├── level_of_theory
├── engine
├── phonon_cell = "primitive"
├── supercell
├── band_points_per_segment
├── frequencies_cm_inv # duplicate of phonon list
├── modes # duplicate of phonon modes
├── phonon # Gamma vibration payload
├── phonon_dos # Gamma-only positive-mode histogram
└── phonon_band # optional
phonon contains signed Γ frequencies, complex components, harmonic energies, zero-point energy, and Cartesian mode vectors. phonon_dos contains bin-center energies in Hartree and cm⁻¹ plus weights. phonon_band contains the reciprocal path and a q-point-by-mode frequency matrix in cm⁻¹.
If a nonperiodic input is supplied, the worker falls back to molecular finite-displacement vibrations while retaining kind: 'phonon'. That branch has no phonon_cell and no phonon_band; phonon_dos is still a finite-mode histogram. Add a guard so this fallback is not accepted as a crystal result:
if (result.phonon_cell !== 'primitive') {
throw new Error('Expected a periodic primitive-cell phonon result.');
}
The generated tako.phonon settings and result reference enumerates every field, type, unit, and availability condition. The returned object does not contain force constants, displaced structures, a q-mesh, or restart records.
Extract path stability evidence
phonon_band.frequencies_cm_inv is indexed first by q point and then by branch. A minimum over that matrix reports the most negative sampled signed frequency, but it does not classify its eigenvector and does not cover off-path q points:
const band = result.phonon_band;
const rows = [];
let minimum = { frequency_cm_inv: Infinity, q_index: -1, mode_index: -1 };
for (let qIndex = 0; qIndex < band.frequencies_cm_inv.length; qIndex += 1) {
const qpoint = band.qpoints[qIndex];
const frequencies = band.frequencies_cm_inv[qIndex];
for (let modeIndex = 0; modeIndex < frequencies.length; modeIndex += 1) {
const frequency = frequencies[modeIndex];
rows.push({ q_index: qIndex, qpoint, mode_index: modeIndex, frequency_cm_inv: frequency });
if (frequency < minimum.frequency_cm_inv) {
minimum = { frequency_cm_inv: frequency, q_index: qIndex, mode_index: modeIndex };
}
}
}
await tako.output('output/phonon-band-rows.json', rows);
await tako.output('output/phonon-path-summary.json', {
path_source: band.path_source,
path_string: band.path_string,
points_per_segment: result.band_points_per_segment,
minimum_sampled_mode: minimum,
coverage: 'selected high-symmetry path only',
});
The current top-level result does not return band eigenvectors, so mode-character confirmation requires another capable workflow. Do not infer longitudinal, transverse, or atom-projected character from a branch index alone.
Supercell and displacement series
Change one convergence variable at a time and preserve each raw result:
const cases = [
{ repeats: [2, 2, 2], displacement: 0.01 },
{ repeats: [3, 3, 3], displacement: 0.01 },
{ repeats: [3, 3, 3], displacement: 0.015 },
];
const summaries = [];
for (const entry of cases) {
const value = await tako.phonon(input, {
calculator,
properties: ['energy', 'forces'],
phononSupercell: entry.repeats,
phononDisplacementAngstrom: entry.displacement,
phononBandPath: 'G X W L G',
phononBandPointsPerSegment: 16,
});
if (!value.phonon_band) throw new Error('Band missing in convergence series.');
const all = value.phonon_band.frequencies_cm_inv.flat();
summaries.push({
supercell: entry.repeats,
displacement_angstrom: entry.displacement,
minimum_path_frequency_cm_inv: Math.min(...all),
result: value,
});
}
await tako.output('output/phonon-convergence.json', summaries);
For a large study, writing every full result inside one summary can be expensive; write each raw result to a separate path and keep only identifiers and diagnostics in the table. Compare identical standardized cells and paths. A different branch order near a degeneracy can require subspace comparison rather than element-by-element arrays.
Reproducibility boundary
Preserve the input structure, periodic cell, preceding relaxation evidence, full calculator construction and model hash, normalized primitive-cell identity, repeats, displacement, path source/string, points per segment, returned units, missing band state, and convergence series. Record input constraints and custom masses as metadata that were not propagated into the periodic primitive calculation. State that the current DOS is Γ-only and that NAC is absent.
The operation is harmonic and path-limited. It does not establish finite-temperature stability, full-Brillouin-zone stability, phonon lifetimes, thermal conductivity, or vibrational thermodynamics. Those conclusions require additional calculations.