Structures: httk-core and httk-atomistic together

This notebook shows two httk₂ modules composing over the shared httk.* namespace: httk-atomistic provides the crystal-structure domain, while httk-core provides the DataLoader used to read a structure from JSON. Their versioned module documentation is listed in the site module directory. It is executed during the docs build, so its outputs reflect the current API.

Building a structure

A Structure is defined by a cell (3×3 matrix), sites (reduced coordinates), a list of species, and species_at_sites naming the species on each site. Species follow the OPTIMADE species object: a name, a list of chemical_symbols, and matching concentration values. Here we build zinc-blende GaAs.

from httk.atomistic import Structure

species = [
    {"name": "Ga", "chemical_symbols": ["Ga"], "concentration": [1.0]},
    {"name": "As", "chemical_symbols": ["As"], "concentration": [1.0]},
]
cell = [[0.0, 2.825, 2.825], [2.825, 0.0, 2.825], [2.825, 2.825, 0.0]]
sites = [[0.0, 0.0, 0.0], [0.25, 0.25, 0.25]]
species_at_sites = ["Ga", "As"]

structure = Structure(cell, sites, species, species_at_sites)
print("species        :", [s.name for s in structure.species])
print("species_at_sites:", structure.species_at_sites)
species        : ['Ga', 'As']
species_at_sites: ('Ga', 'As')

Round-tripping through the primitive view

StructurePrimitiveView presents any structure backend as an spglib-like (lattice, positions, numbers) tuple — bare atomic numbers instead of named species. UnitcellStructureView presents it back as a full Structure.

from httk.atomistic import StructurePrimitiveView, UnitcellStructureView

lattice, positions, numbers = StructurePrimitiveView(structure)
print("atomic numbers:", numbers)

roundtrip = UnitcellStructureView(StructurePrimitiveView(structure))
print("cell preserved          :", roundtrip.cell == structure.cell)
print("species_at_sites preserved:", roundtrip.species_at_sites == structure.species_at_sites)
atomic numbers: (31, 33)
cell preserved          : True
species_at_sites preserved: True

When the primitive view does not apply

The primitive representation carries only bare atomic numbers, so every site must be a single, unattached chemical element. A structure with a vacancy species cannot become a primitive triple — building the view raises TypeError.

vacancy_species = [
    {"name": "Ga", "chemical_symbols": ["Ga"], "concentration": [1.0]},
    {"name": "Vac", "chemical_symbols": ["vacancy"], "concentration": [1.0]},
]
with_vacancy = Structure(cell, sites, vacancy_species, ["Ga", "Vac"])

try:
    StructurePrimitiveView(with_vacancy)
except TypeError as error:
    print("TypeError:", error)
TypeError: This structure cannot be represented as a primitive structure (species 'Vac' is not a single, unattached chemical element)

Loading a structure from JSON via httk-core

The quartet can just as well come from data. Here httk-core’s DataLoader parses a structure-shaped JSON document (passed inline with kind="content"), and httk-atomistic constructs the Structure from it — the two modules composing over the shared namespace.

import json

from httk.core import DataLoader

document = json.dumps(
    {
        "cell": cell,
        "sites": sites,
        "species": species,
        "species_at_sites": species_at_sites,
    }
)

record = DataLoader("gaas-structure", document, kind="content").data
from_json = Structure(
    record["cell"], record["sites"], record["species"], record["species_at_sites"]
)
print("equal to the hand-built structure:", from_json == structure)
equal to the hand-built structure: True