Structures and Calculators
On this page
- tako.calculator.gxtb
- tako.calculator.gfn2
- tako.calculator.mlip
- tako.calculator.dft
- tako.structure.atom
- tako.structure.benzene
- tako.structure.crystal
- tako.structure.bulk
- tako.structure.Atoms
- tako.structure.get_chemical_symbols
- tako.structure.get_chemical_formula
- tako.structure.get_positions
- tako.structure.get_scaled_positions
- tako.structure.get_cell
- tako.structure.set_positions
- tako.structure.set_scaled_positions
- tako.structure.set_cell
- tako.structure.addAtoms
- tako.structure.addFractionalAtoms
- tako.structure.delete
- tako.structure.translate
- tako.structure.rotate
- tako.structure.duplicate
- tako.structure.repeat
- tako.structure.wrap
- tako.structure.copy
- tako.structure.fix
- tako.structure.setCellOrigin
Calculator narrative and method-selection guidance live in Calculator Construction and Validation and the Calculator Reference.
A calculator is a small reusable object built once with tako.calculator.gxtb, gfn2, mlip, or dft. Construction is synchronous and only records a method specification; it does not load a model or run anything. Every calculator carries capabilities(), elementSupport(structure), validate(operation, request), and readiness(manifest, records) inspection methods. Passing structure to validate performs the same fast supported-element check used by the UI before any model or WASM is loaded.
Naming rule for this namespace: snake_case methods (get_positions, set_cell, get_chemical_formula, …) deliberately mirror ASE’s Atoms API name-for-name so ASE muscle memory transfers; Tako-native helpers with no ASE counterpart use camelCase (addAtoms, addFractionalAtoms, setCellOrigin). The two styles coexisting is intentional, not drift — a snake_case name is a promise of ASE-matching semantics.
Every tako.structure.* editing call is an immutable, ASE-shaped helper: it takes a Structure (and, for the mutators, extra arguments) and returns a brand-new Structure without modifying its input — duplicate is the one exception, returning { structure, newIds } so the caller can learn the ids of the atoms it just created. Cartesian positions and cell vectors are in Å; rotation angles are in degrees; fractional/scaled coordinates are dimensionless and are not automatically wrapped into [0, 1) unless wrap() is called explicitly. Atom selectors are not interchangeable across calls: delete and fix take 0-based array indices into structure.atoms, while translate, rotate, and duplicate take atom id numbers — mixing the two up silently selects the wrong atoms or throws an out-of-range error.
Method choice is part of the scientific record. g-xTB is the balanced default and provides the faster sTDA route from its converged electronic state. GFN2 adds implicit solvation and remains the accuracy-first sTDA default for absorption-band positions. MLIPs target fast neutral, closed-shell and periodic work. DFT exposes periodic LDA/VWN plus PBE, r2SCAN, and molecular SKALA 1.1. LDA/VWN is the validated GTH-DZVP-MOLOPT-SR/GTH-PADE identity and has no empirical dispersion by default. The UI defaults new DFT selections to PBE/def2-SVP (and restores the user’s last-run calculator settings thereafter). Semantic script levels still resolve bare pbe/r2scan to def2-SVP on molecules and GTH-DZVP-MOLOPT-SR/GTH-PBE on periodic cells. Explicit PBC bases include GTH-SZV-MOLOPT-SR, UZH GTH-SVP/DZVP/TZVP/TZV2P-MOLOPT-PBE, and legacy narrow GTH sets; elementSupport reports Z coverage before any WASM load. SKALA 1.1 resolves to def2-SVP and remains molecular-only.
tako.calculator.gxtb
tako.calculator.gxtb(options?: { dispersion?: 'none' | 'd3-bj' | 'd4-rev'; charge?: number; unpaired?: number; spinPolarized?: boolean; scf?: object }) => TakoScriptCalculator
Constructs the balanced default g-xTB calculator through tb.rs.
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.dispersion | 'none' | 'd3-bj' | 'd4-rev' | 'd4-rev' | Selects no correction, DFT-D3 with the published ωB97M reference-functional parameters, or native self-consistent DFT-revD4. |
options.charge | number | 0 | Total charge. |
options.unpaired | integer | 0 | Number of unpaired electrons. |
options.spinPolarized | boolean | false | Requests open-shell treatment. |
options.scf | object | backend defaults | Partial SCF controls. |
Returns: TakoScriptCalculator with engine: ‘gfn2’, levelOfTheory: ‘gxtb’, and tb runtime readiness.
- g-xTB supports molecular and periodic energy, forces, stress, optimization, MD, phonons, vibrations, reaction paths, and transition-state work.
- The g-xTB parametrization is molecular; the theory itself is unreliable under periodic boundary conditions. Periodic g-xTB runs proceed but should be treated with caution — prefer GFN2-xTB, an MLIP, or periodic DFT for crystals.
- DFT-revD4 is the native g-xTB dispersion model and the default. DFT-D3 uses the published ωB97M D3(BJ) record because no separate g-xTB-specific D3 fit has been published; result metadata records wb97m explicitly.
- g-xTB supports sTDA by passing its accepted orbitals, energies, and occupations directly to the simplified response kernel. The cached density remains unchanged, and response dipole integrals are evaluated in the calculator-owned q-vSZP basis. It does not support GFN2 implicit solvation.
const calculator = tako.calculator.gxtb({ dispersion: 'd4-rev', charge: -1, unpaired: 1 });
tako.calculator.gfn2
tako.calculator.gfn2(options?: { levelOfTheory?: 'gfn2'; dispersion?: 'default' | 'none' | 'd4'; charge?: number; unpaired?: number; spinPolarized?: boolean; scf?: object; solvation?: object }) => TakoScriptCalculator
Constructs a reusable semi-empirical GFN2-xTB calculator object with a normalized method specification and inspection methods.
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.levelOfTheory | 'gfn2' | 'gfn2' | Selects GFN2-xTB independently of its dispersion correction. |
options.dispersion | 'default' | 'none' | 'd4' | 'default' | Selects dispersion separately; ‘default’ resolves to native D4 for GFN2-xTB. |
options.charge | number | 0 | Total molecular charge in elementary-charge units; any finite number is accepted (not rounded). |
options.unpaired | integer | 0 | Number of unpaired electrons (backend spin-population input); floored and clamped to >= 0. |
options.spinPolarized | boolean | false | Requests the unrestricted/open-shell SCF treatment. |
options.scf | object | backend defaults | Partial override of SCF cycle limits, energy/density thresholds, electronic temperature, mixer, and temperature annealing. |
options.solvation | object | { enabled: false, model: 'alpb-cds', solvent: 'water', ... } | Partial override requesting an implicit-solvent model ({ enabled, model, solvent, electrostatic, bornKernel, cds, cm5, shift }). |
Returns: TakoScriptCalculator: { engine: ‘gfn2’, levelOfTheory, charge, unpaired, spinPolarized, dispersion, scf, solvation, capabilities(): AseCalculatorCapabilities, validate(operation, request?): { ok: boolean; reasons: string[] }, readiness(manifest?, records?): { ready: boolean; summary: string[] } }.
- Construction is synchronous and does not download or load anything; it only normalizes the method specification.
- capabilities() for GFN2 reports { name: ‘Gfn2Calculator’, backend: ‘tb.rs’, properties: [‘energy’,‘forces’,‘stress’,‘charges’,‘dipole’], operations: […COMMON_OPERATIONS,‘stda’,‘reactionPath’,‘transitionState’], supportsPbc: true, supportsCharge: true, supportsSpin: true, supportsCellOptimization: true, dynamics, phonons, analysis.xrd }.
- validate(operation, { properties }) returns { ok: false, reasons } when an operation is unsupported, when a requested property is unavailable at this level, or when an electronic property (dos, pdos, charges, electronDensity, chargeDensity, nci, wfn) is requested for an operation other than ‘singlePoint’.
- readiness(manifest, records) reports asset status for the tb WASM runtime; with no manifest/records it only describes requirements, not the live cache.
- Charge and spin describe the modeled electronic state, not correction knobs — construct one calculator per intended electronic state rather than mutating charge/unpaired on a shared object.
const calculator = tako.calculator.gfn2({ dispersion: 'default', charge: 1, unpaired: 1, spinPolarized: true });
const check = calculator.validate('optimization', { properties: ['energy', 'forces'] });
tako.calculator.mlip
tako.calculator.mlip(options?: { levelOfTheory?: string; runtime?: string; model?: string }) => TakoScriptCalculator
Constructs a reusable machine-learned interatomic potential (MLIP) calculator object with a normalized runtime/model pairing.
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.levelOfTheory | 'nequix' | 'nequix-phono' | 'nequip-s' | 'nequip-l' | 'equiformer' | 'equiformer-gradient' | 'nequip-s' | Selects a registered runtime + weight-set pairing. |
options.runtime | 'nequix' | 'nequip' | 'equiformer' | level-dependent (or derived from model, see notes) | Overrides the inference runtime; only meaningful with a matching model. |
options.model | 'nequix-mp-1' | 'nequix-mp-1-pft' | 'nequip-s' | 'nequip-l' | 'equiformer' | 'equiformer-gradient' | level-dependent | Overrides the registered weight identifier. |
Returns: TakoScriptCalculator: { engine: ‘mlip’, levelOfTheory, runtime, model, capabilities(): AseCalculatorCapabilities, validate(operation, request?): { ok: boolean; reasons: string[] }, readiness(manifest?, records?): { ready: boolean; summary: string[] } }.
- An explicitly named model pins its own runtime (nequix-mp-1/-pft => ‘nequix’, equiformer/-gradient => ‘equiformer’, nequip-s/-l => ‘nequip’); the level’s default runtime applies only when the model is also left at its default.
- capabilities() for MLIP reports { name: ‘MlipCalculator’, backend: runtime, properties: [‘energy’,‘forces’,‘stress’], operations: […COMMON_OPERATIONS,‘reactionPath’,‘transitionState’], supportsPbc: true, supportsCharge: false, supportsSpin: false, supportsCellOptimization: true, dynamics, phonons, analysis.xrd }.
- An MLIP calculator has no charge, multiplicity, orbital, or solvent state; passing charge/unpaired/spinPolarized-like fields has no effect on the model. Use tako.calculator.gfn2 whenever the question depends on electron count, spin, or a dielectric environment.
- readiness(manifest, records) describes required WASM runtime and model-weight assets relative to the manifest/records supplied; it does not itself probe the browser cache.
const calculator = tako.calculator.mlip({ levelOfTheory: 'nequix' });
const ready = calculator.readiness(manifest, assetRecords);
tako.calculator.dft
tako.calculator.dft(options: { levelOfTheory: 'lda' | 'pbe' | 'r2scan' | 'skala'; dispersion?: 'default' | 'none' | 'd3-bj'; charge?: number; unpaired?: number; spinPolarized?: boolean; kpoints?: { mode: 'auto' | 'gamma' | 'custom'; mesh?: [number, number, number] }; scf?: object }) => TakoScriptCalculator
Constructs a DFT calculator through the ase.rs QC adapter.
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.levelOfTheory | 'lda' | 'pbe' | 'r2scan' | 'skala' | — | Required functional identity. LDA/VWN is periodic-only and pins GTH-DZVP-MOLOPT-SR/GTH-PADE; Tako resolves the other broad-coverage bases from the input boundary conditions. |
options.dispersion | 'default' | 'none' | 'd3-bj' | 'none' for LDA/VWN; 'default' otherwise | Selects dispersion separately; ‘default’ resolves to none for LDA/VWN and functional-specific D3(BJ) for the other QC methods. |
options.charge | number | 0 | Total molecular charge. |
options.unpaired | integer | 0 | Number of unpaired electrons. |
options.spinPolarized | boolean | false | Requests open-shell treatment. |
options.kpoints | { mode: 'auto' | 'gamma' | 'custom'; mesh?: [number, number, number] } | { mode: 'auto' } | Reciprocal-space sampling for periodic cells: ‘auto’ picks the smallest mesh with k·L ≥ 15 Å per lattice vector, ‘gamma’ forces the Γ point, ‘custom’ uses mesh (entries clamped to 1–48). Molecular runs ignore it. |
options.scf | object | — | Unified SCF surface overrides (energyThreshold, densityThreshold, maxIterations, mixerDamping, electronicTemperatureKelvin). The electronic temperature sets periodic Fermi–Dirac smearing (σ = kB·T); metals often need 1000–2000 K to converge, and the default 300 K is negligible for gapped systems. |
Returns: TakoScriptCalculator with engine: ‘qc’, a geometry-aware DFT level, elementSupport(structure), and synchronous validation.
- Molecular PBE, r2SCAN, and SKALA 1.1 use def2-SVP. The bundled def2 table covers H-La and Hf-Rn; Ce-Lu are absent and are rejected during selection.
- LDA/VWN is periodic-only and uses the tested GTH-DZVP-MOLOPT-SR/GTH-PADE pair.
dispersion: "default"resolves to none because no D3 correction was validated for this public identity. Automatic force/stress requests use total-energy finite differences until the periodic LDA analytical derivative path is translated. - Default dispersion uses published BJ-damped D3 parameters: pbe for PBE, r2scan for r2SCAN, and the skala-1.0 D3 parameter record for SKALA 1.1. The SKALA parameter-record name identifies the published fit; it does not change the selected SKALA 1.1 electronic model.
- For molecules, all three functionals support single points, optimization, MD, vibrations, reaction paths, and transition states.
- For full 3D PBC, semantic PBE and r2SCAN default to GTH-DZVP-MOLOPT-SR/GTH-PBE (Z=1–56, 72–86). Explicit bases include GTH-SZV-MOLOPT-SR (fastest broad), UZH GTH-SVP-MOLOPT-PBE (heavy-only fast), GTH-DZVP/TZVP/TZV2P-MOLOPT-PBE (UZH quality ladder), legacy narrow GTH-DZVP/TZV2P/QZV3P, and def2. GTH families support energy, forces, stress, optimization, cell relaxation, MD, phonons, vibrations, and periodic analyses (charges, DOS/PDOS, density cubes, NCI, ESP, Fukui, HDF5). Periodic def2 carries the same forces/stress and force-driven operations for every covered element: all-electron cells (every atom H–Kr) differentiate analytically, and scalar-ECP cells (any atom Rb+) automatically fall back to total-energy finite differences, which cost one converged SCF per displacement. Molecular-only formats (orbital cubes, ELF, Molden, WFN) stay unavailable under k-point PBC. SKALA 1.1 is molecular-only.
- elementSupport(structure) is a synchronous lookup over precomputed element sets. It reports requestedElements, supportedElements, missingElements, basis, and pseudopotential (with Z-range reasons on failure). validate(operation, { structure, properties }) runs the same check used by both UI selectors, and execution rejects before model or WASM dispatch when it fails.
- Explicit basis-bearing DFT identities remain readable for archived workspaces, but new scripts should use the four semantic levels above.
- Periodic QC derives its FFT mesh from a fixed 100 Ha reciprocal kinetic-energy cutoff using qc.rs/PySCF cutoff_to_mesh semantics. The mesh therefore scales with lattice vectors, so energies from different cell volumes remain on one reciprocal-resolution control instead of reusing a fixed mesh count.
- All three phases of a metallic system can carry odd per-cell electron counts under a k-point mesh: electrons fill the sampled ensemble (PySCF KRKS/KUKS semantics), so closed-shell runs on metals like LiC6 or primitive-cell Al are valid without artificial spin. Pair them with an elevated electronicTemperatureKelvin when the SCF oscillates.
- SKALA readiness includes the separate skala-1.1 model asset. LDA/VWN, PBE, and r2SCAN require only the QC WASM module.
const calculator = tako.calculator.dft({ levelOfTheory: 'r2scan', dispersion: 'default' });
const check = calculator.validate('singlePoint', { structure, properties: ['energy', 'forces'] });
tako.structure.atom
tako.structure.atom(element: string, positionOrOptions?: [number, number, number] | { title?: string; position?: [number, number, number] }) => Structure
Creates a non-periodic, single-atom Structure at an optional Cartesian position.
| Parameter | Type | Default | Contract |
|---|---|---|---|
element | string | — | Element symbol for the atom. |
positionOrOptions | [x, y, z] | { title?: string; position?: [x, y, z] } | [0, 0, 0] | A bare [x, y, z] tuple (Å), or an options object with an optional title and position. |
Returns: Structure with one atom (id 1), cell: null, title defaulting to ’
- Always produces a non-periodic structure (cell is null regardless of position).
const na = tako.structure.atom('Na', [0, 0, 0]);
tako.structure.benzene
tako.structure.benzene(options?: { title?: string }) => Structure
Creates a planar, non-periodic benzene ring (6 carbons at radius 1.397 Å, 6 hydrogens at radius 2.479 Å, both in the z = 0 plane).
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.title | string | 'Benzene' | Title for the returned structure. |
Returns: Structure with 12 atoms (ids 1-6 carbons, 7-12 hydrogens), cell: null.
tako.structure.crystal
tako.structure.crystal(options: { title: string; cell: [[number,number,number],[number,number,number],[number,number,number]]; fractionalAtoms: Array<[string, [number, number, number]]> }) => Structure
Creates a periodic Structure from explicit lattice vectors and a list of fractional-coordinate atoms.
| Parameter | Type | Default | Contract |
|---|---|---|---|
options.title | string | — | Title for the returned structure. |
options.cell | [[number,number,number] x3] | — | Three lattice vectors in Å. |
options.fractionalAtoms | Array<[element, [fx, fy, fz]]> | — | Element symbol and fractional (dimensionless) coordinate for each atom, in the order they receive ids starting at 1. |
Returns: Structure with atoms Cartesian-placed from fractionalAtoms x cell, cell: { vectors: options.cell, scale: 1 }.
- Unlike most other structure builders (e.g. Atoms, bulk), this call does not validate the shape of cell or fractionalAtoms before use (no assertCell/assertVec3 check) — a malformed cell surfaces as a downstream numeric error rather than a clear validation message.
- Atoms built by crystal() are tagged layerId: ‘molecule’ even though the structure is periodic, unlike Atoms()/bulk() which tag periodic atoms layerId: ‘crystal’; this only affects the app’s layer grouping, not the physics.
const nacl = tako.structure.crystal({
title: 'NaCl',
cell: [[5.64, 0, 0], [0, 5.64, 0], [0, 0, 5.64]],
fractionalAtoms: [['Na', [0, 0, 0]], ['Cl', [0.5, 0.5, 0.5]]],
});
tako.structure.bulk
tako.structure.bulk(symbol: string, crystalstructure: string, a: number, options?: { c?: number; covera?: number; cubic?: boolean; orthorhombic?: boolean; title?: string }) => Structure
tako.structure.bulk(symbol: string, crystalstructure: string, options: { a: number; c?: number; covera?: number; cubic?: boolean; orthorhombic?: boolean; title?: string }) => Structure
Creates a periodic bulk Structure for a single element in a named crystal structure (ASE bulk()-style).
| Parameter | Type | Default | Contract |
|---|---|---|---|
symbol | string | — | A single element symbol (a formula naming more than one element throws). |
crystalstructure | 'sc' | 'bcc' | 'fcc' | 'diamond' | 'hcp' | — | Case/underscore/hyphen-insensitive; accepts aliases like ‘simple-cubic’, ‘body-centered-cubic’, ‘face-centred-cubic’, ‘hexagonal-close-packed’. |
a | number | — | Lattice constant a in Å, either as the 3rd positional argument or as options.a; required (throws if neither is a positive finite number). |
options.cubic | boolean | false | For bcc/fcc/diamond, builds the conventional (multi-atom) cubic cell instead of the primitive cell. |
options.orthorhombic | boolean | false | For hcp, builds a 4-atom orthorhombic cell instead of the 2-atom hexagonal cell. |
options.c | number | hcp only: sqrt(8/3) * a, or covera * a if covera is given | hcp c lattice constant in Å. |
options.covera | number | sqrt(8/3) | hcp c/a ratio, used to derive c when c is not given directly. |
options.title | string | '<symbol> <crystalstructure>' | Title for the returned structure. |
Returns: Periodic Structure built by delegating to tako.structure.Atoms with pbc: true and the scaled_positions for the chosen lattice.
const cu = tako.structure.bulk('Cu', 'fcc', 3.615, { cubic: true });
tako.structure.Atoms
tako.structure.Atoms(symbols: string | string[], options?: { title?: string; positions?: [number,number,number][]; scaled_positions?: [number,number,number][]; scaledPositions?: [number,number,number][]; cell?: [[number,number,number],[number,number,number],[number,number,number]]; pbc?: boolean | [boolean,boolean,boolean]; layerId?: string }) => Structure
Creates a Structure from element symbols and optional positions/cell (ASE Atoms()-style constructor).
| Parameter | Type | Default | Contract |
|---|---|---|---|
symbols | string | string[] | — | A chemical-formula string parsed left-to-right by element+count tokens (e.g. ‘H2O’ -> [‘H’,‘H’,‘O’]), or an explicit array of element symbols, one per atom. |
options.positions | [x,y,z][] | — | Cartesian positions in Å, one per atom (array length must equal symbols length). |
options.scaled_positions / scaledPositions | [fx,fy,fz][] | — | Fractional positions, one per atom; requires options.cell (throws otherwise). Both spellings are accepted aliases. |
options.cell | [[number,number,number] x3] | — | Three lattice vectors in Å; presence of a cell is what makes the structure periodic. |
options.pbc | boolean | [boolean,boolean,boolean] | — | Accepted for ASE-signature compatibility but not read: periodicity is determined solely by whether options.cell is given, not by this flag. |
options.layerId | string | 'crystal' if cell is given, else 'molecule' | Layer tag written onto every created atom. |
options.title | string | 'Atoms' | Title for the returned structure. |
Returns: Structure with one atom per symbol; cell: { vectors, scale: 1 } if options.cell given, else null.
- If neither positions nor scaled_positions is given, every atom is placed at the origin [0, 0, 0].
- options.pbc is accepted but ignored — passing { cell, pbc: false } still produces a periodic structure, because Structure has no independent pbc flag (only cell: Cell | null).
const water = tako.structure.Atoms(['O', 'H', 'H'], {
title: 'Water',
positions: [[0, 0, 0], [0.76, 0.59, 0], [-0.76, 0.59, 0]],
});
tako.structure.get_chemical_symbols
tako.structure.get_chemical_symbols(structure: Structure) => string[]
Returns each atom’s element symbol in structure.atoms order.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to read. |
Returns: string[], same length and order as structure.atoms.
tako.structure.get_chemical_formula
tako.structure.get_chemical_formula(structure: Structure, mode?: 'hill' | 'reduce' | 'all') => string
Returns a formula string built from raw per-element atom counts, in one of three symbol orderings.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to read. |
mode | 'hill' | 'reduce' | 'all' | 'hill' | Symbol ordering: ‘hill’ puts C first, then H, then remaining elements alphabetically (pure alphabetical if there is no carbon); ‘reduce’ and ‘all’ order by each element’s first occurrence in structure.atoms. |
Returns: String such as ‘C6H6’; each element appears once, suffixed with its atom count when the count is greater than 1.
- Counts are the real atom counts, never divided by a common factor — mode: ‘reduce’ does not produce an empirically-reduced formula the way ASE’s get_chemical_formula(mode=‘reduce’) does.
- mode: ‘all’ is expected (by ASE convention) to repeat every atom’s symbol without deduplication, but the implementation applies a first-occurrence de-duplication after ordering regardless of mode, so ‘all’ currently produces the same unique, counted output as ‘reduce’ (only ‘hill’ differs, by ordering). Verify against source before relying on ‘all’ returning a non-deduplicated per-atom list.
tako.structure.get_chemical_formula(benzene); // 'C6H6'
tako.structure.get_positions
tako.structure.get_positions(structure: Structure) => [number, number, number][]
Returns the Cartesian position of every atom.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to read. |
Returns: [x, y, z][] in Å, same order as structure.atoms.
tako.structure.get_scaled_positions
tako.structure.get_scaled_positions(structure: Structure) => [number, number, number][]
Returns each atom’s fractional (scaled) coordinate relative to the structure’s cell.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to read. |
Returns: [fx, fy, fz][], dimensionless, same order as structure.atoms.
- If structure.cell is null, this returns each atom’s stored fx/fy/fz fields directly (which equal its Cartesian x/y/z for atoms created without a cell) rather than throwing.
- Values are not wrapped into [0, 1) — an atom placed outside the cell keeps out-of-range fractional coordinates until wrap() is called.
tako.structure.get_cell
tako.structure.get_cell(structure: Structure) => [[number,number,number],[number,number,number],[number,number,number]] | null
Returns the three lattice vectors of the structure, or null if it is not periodic.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to read. |
Returns: 3x3 array of Å lattice vectors, or null when structure.cell is null.
tako.structure.set_positions
tako.structure.set_positions(structure: Structure, positions: [number,number,number][], options?: { title?: string }) => Structure
Returns a new Structure with every atom moved to an explicit Cartesian position.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
positions | [x,y,z][] | — | One Cartesian position per atom, in Å; length must equal structure.atoms.length (throws otherwise). |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with updated x/y/z (and recomputed fx/fy/fz if a cell is present) and refreshed elements/elementCounts.
const moved = tako.structure.set_positions(structure, tako.structure.get_positions(structure).map(([x, y, z]) => [x, y, z + 1]));
tako.structure.set_scaled_positions
tako.structure.set_scaled_positions(structure: Structure, positions: [number,number,number][], options?: { title?: string }) => Structure
Returns a new Structure with every atom moved to an explicit fractional position, converted to Cartesian via the current cell.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure; must already have a cell (throws otherwise). |
positions | [fx,fy,fz][] | — | One fractional coordinate per atom; length must equal structure.atoms.length. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with x/y/z recomputed from the fractional inputs and the existing cell.
- Throws “set_scaled_positions requires a cell.” when structure.cell is null.
tako.structure.set_cell
tako.structure.set_cell(structure: Structure, cell: [[number,number,number],[number,number,number],[number,number,number]], options?: { scale_atoms?: boolean; title?: string }) => Structure
Returns a new Structure with a different cell, either keeping Cartesian positions fixed or keeping fractional positions fixed.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
cell | [[number,number,number] x3] | — | New lattice vectors in Å. |
options.scale_atoms | boolean | false | false: keep every atom’s current Cartesian position and recompute fractional coordinates under the new cell. true: keep every atom’s current fractional coordinates and recompute Cartesian positions under the new cell. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with cell: { vectors: cell, scale: 1 } and positions adjusted per scale_atoms.
const scaled = tako.structure.set_cell(structure, [[6, 0, 0], [0, 6, 0], [0, 0, 6]], { scale_atoms: true });
tako.structure.addAtoms
tako.structure.addAtoms(structure: Structure, atoms: Structure | Structure[], options?: { title?: string }) => Structure
Returns a new Structure with the atoms of one or more other Structures appended, assigning fresh sequential ids.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
atoms | Structure | Structure[] | — | Additional structure(s) whose atoms are appended, in argument/array order; each atom’s id is replaced starting at base’s current max id + 1. |
options.title | string | structure.title | Title for the returned structure. |
Returns: New Structure containing base’s atoms followed by the appended atoms, with elements/elementCounts recomputed.
- The base structure’s cell is preserved: appending to a periodic slab/crystal keeps it periodic, and the appended atoms’ fractional coordinates are recomputed from their Cartesian positions against that cell. Appended atom positions are always interpreted as Cartesian Å — use addFractionalAtoms to place atoms by fractional coordinates.
const co = tako.structure.addAtoms(tako.structure.atom('C', [0, 0, 0]), tako.structure.atom('O', [0, 0, 1.15]));
tako.structure.addFractionalAtoms
tako.structure.addFractionalAtoms(structure: Structure, atoms: Array<[string, [number, number, number]]>, options?: { title?: string }) => Structure
Returns a new periodic Structure with atoms appended at explicit fractional coordinates, converted via the current cell.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure; must already have a cell (throws “addFractionalAtoms requires a periodic structure with a cell.” otherwise). |
atoms | Array<[element, [fx, fy, fz]]> | — | Element symbol and fractional coordinate for each new atom; ids assigned starting at base’s current max id + 1. |
options.title | string | structure.title | Title for the returned structure. |
Returns: New Structure with base’s atoms plus the new atoms (Cartesian computed from fractional x cell), and the base’s cell preserved.
const doped = tako.structure.addFractionalAtoms(mapbi3, [['H', [0.02, 0.08, 0.05]]], { title: mapbi3.title });
tako.structure.delete
tako.structure.delete(structure: Structure, selector: number[] | ((atom, index: number) => boolean) | { symbol?: string; element?: string; indices?: number[]; ids?: number[] }, options?: { title?: string }) => Structure
Returns a new Structure with the matched atoms removed and the remaining atoms renumbered.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
selector | number[] | predicate | { symbol?, element?, indices?, ids? } | — | An array of 0-based atom-array indices (throws if any index is out of range); a predicate (atom, index) => boolean; or an object matching by explicit indices, atom ids, or element/symbol. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with matched atoms removed; every remaining atom is renumbered id = 1..N in its new order (original ids are not preserved).
- Selector indices are array positions (0-based), not the atoms’ persistent id field — the same convention as fix, and different from translate/rotate/duplicate, which take id values.
const noHydrogens = tako.structure.delete(structure, { element: 'H' });
tako.structure.translate
tako.structure.translate(structure: Structure, ids: number[], delta: [number, number, number], options?: { title?: string }) => Structure
Returns a new Structure with the atoms matching the given ids shifted by a Cartesian offset.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
ids | number[] | — | Atom id values (not array indices) to move; ids with no matching atom are silently ignored. |
delta | [dx, dy, dz] | — | Cartesian offset in Å applied to each selected atom. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with the selected atoms’ x/y/z shifted by delta (and fx/fy/fz recomputed if a cell is present); unselected atoms are unchanged.
const shifted = tako.structure.translate(structure, [7, 8], [0, 0, 1.5]);
tako.structure.rotate
tako.structure.rotate(structure: Structure, ids: number[], options: { center: [number, number, number]; rotations: Array<{ axis: [number, number, number]; degrees: number }>; title?: string }) => Structure
Returns a new Structure with the atoms matching the given ids rotated in sequence about a shared center.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
ids | number[] | — | Atom id values (not array indices) to rotate. |
options.center | [x, y, z] | — | Cartesian rotation center in Å. |
options.rotations | Array<{ axis: [x,y,z]; degrees: number }> | — | Ordered list of axis/angle rotations (Rodrigues’ formula), each applied to the result of the previous one — not combined into a single matrix. Near-zero axis length or angle entries are skipped. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with selected atoms rotated about options.center (fx/fy/fz recomputed if a cell is present); unselected atoms are unchanged.
const spun = tako.structure.rotate(structure, [1, 2, 3], { center: [0, 0, 0], rotations: [{ axis: [0, 0, 1], degrees: 90 }] });
tako.structure.duplicate
tako.structure.duplicate(structure: Structure, ids: number[], delta: [number, number, number], options?: { title?: string }) => { structure: Structure; newIds: number[] }
Returns a new Structure with copies of the atoms matching the given ids, offset by delta, plus the ids assigned to the copies.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
ids | number[] | — | Atom id values (not array indices) to duplicate. |
delta | [dx, dy, dz] | — | Cartesian offset in Å applied to each duplicate, relative to its source atom. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: { structure: Structure (original atoms plus duplicates appended), newIds: number[] } — newIds are fresh sequential ids continuing after the structure-wide max id, listed in structure order (not selector order).
- This is the only tako.structure.* editing call that does not return a bare Structure — the caller needs newIds to select/highlight the copies.
const { structure: withCopy, newIds } = tako.structure.duplicate(structure, [1], [2, 0, 0]);
tako.structure.repeat
tako.structure.repeat(structure: Structure, repeats: [number, number, number], options?: { title?: string }) => Structure
Returns a new periodic Structure tiled nx x ny x nz times, with the cell scaled to match.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure; must already have a cell (throws “repeat requires a cell.” otherwise). |
repeats | [nx, ny, nz] | — | Three positive integer repeat counts. |
options.title | string | '<structure.title> nx x ny x nz' | Title for the returned structure. |
Returns: New Structure with nxnynz*atoms.length atoms (ids renumbered 1..N) and cell vectors scaled by [nx, ny, nz] respectively.
const supercell = tako.structure.repeat(unitCell, [2, 2, 1]);
tako.structure.wrap
tako.structure.wrap(structure: Structure, options?: { title?: string }) => Structure
Returns a new Structure with every atom’s fractional coordinates wrapped into [0, 1).
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure; must already have a cell (implemented via set_scaled_positions, which throws “set_scaled_positions requires a cell.” otherwise). |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with fx/fy/fz each wrapped independently via value - floor(value), and Cartesian x/y/z recomputed from the wrapped fractional coordinates.
tako.structure.copy
tako.structure.copy(structure: Structure, options?: { title?: string }) => Structure
Returns a deep (JSON round-trip) clone of the structure, optionally with a new title.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Structure to clone. |
options.title | string | unchanged | Overrides the title on the returned copy. |
Returns: New Structure, deep-equal to the input except for an optional title change.
tako.structure.fix
tako.structure.fix(structure: Structure, indices: number[], options?: { move?: [boolean, boolean, boolean] }) => Structure
Returns a new Structure with an explicit per-axis movement mask (atom.selective) written onto the selected atoms.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure (not mutated). |
indices | number[] | — | 0-based atom-array indices (not atom ids) to constrain — the same convention as delete’s array selector. |
options.move | [boolean, boolean, boolean] | [false, false, false] | Per-axis (x, y, z) freedom mask; true = free to move on that axis. Omitting move freezes all three axes for the selected atoms. |
Returns: New Structure where each selected atom has atom.selective set to the given (or default all-false) 3-tuple; unselected atoms are unchanged.
- The selective mask is forwarded verbatim into the calculation WASM input for any atom that has it set, and is consumed there to freeze the corresponding Cartesian degrees of freedom during optimization/molecular dynamics.
- fix always writes an explicit mask, including an all-true (fully free) one. The app’s own constraint UI (setAtomConstraints in src/store.ts) additionally deletes atom.selective entirely when the mask is all-true, because a present selective field (even all-true) changes VASP POSCAR export (“Selective dynamics”); tako.structure.fix itself does not do this deletion, so a script that wants to fully release a constraint should delete the field itself rather than call fix with move: [true, true, true] and expect the field to disappear.
const slabFixed = tako.structure.fix(slab, [0, 1, 2, 3]); // freeze the bottom four indices in place
tako.structure.setCellOrigin
tako.structure.setCellOrigin(structure: Structure, origin: [number, number, number], options?: { title?: string }) => Structure
Returns a new Structure whose cell’s fractional origin is moved to a new Cartesian point, without moving any atom’s Cartesian position.
| Parameter | Type | Default | Contract |
|---|---|---|---|
structure | Structure | — | Base structure; must already have a cell (throws “setCellOrigin requires a cell.” otherwise). |
origin | [x, y, z] | — | New Cartesian origin (Å) for the cell’s fractional coordinate system. |
options.title | string | unchanged | Overrides the title on the returned structure. |
Returns: New Structure with cell.origin set to origin and every atom’s fx/fy/fz recomputed relative to it; every atom’s Cartesian x/y/z is unchanged.
- This is a native Tako addition with no ASE equivalent — it only changes where the fractional coordinate system is anchored, not the physical geometry.
Return to the Tako Script API index.