Skip to content

Oxide surface NEB: NiO builds the polar (111) termination — needs per-structure Miller indices #5

Description

@Azeezakinyemi999

The pipeline uses one global MILLER = (1, 1, 1) (pipeline.ipynb, Part 1 config) for every structure. The oxide branch of build_slab (models/structure.py) applies these indices to the spglib primitive cell, which has different consequences per oxide:

  • **Cr₂O₃ (corundum): ** (111) of the rhombohedral primitive cell = the hexagonal (0001) basal plane — the standard, stable corundum surface. Correct as-is, no action needed.
  • NiO (rock salt): (111) of the FCC-primitive cell = cubic NiO(111) — a polar Tasker type-III surface (alternating pure-Ni and pure-O planes). Polar terminations have formally divergent surface energy and heavily reconstruct in reality; H₂ dissociation barriers computed on an ideal polar slab are not physically meaningful. The stable nonpolar cleavage is NiO(100) (mixed Ni+O planes).

Note the index conversion trap: cubic (100) is not (1,0,0) of the primitive cell — in the FCC-primitive basis it becomes (0,1,1)-type indices, and the exact permutation depends on spglib's standardized cell orientation.

NiO is currently excluded from Parts 1–2 (surface NEB + permeation). Its Part 3 bulk diffusivity is unaffected and should keep running.

Plan to solve:

  • Add a per-structure 'miller' key to METAL_CONFIGS in pipeline.ipynb (default: the global MILLER), and pass cfg['miller'] in the Part 1/2 generation loops instead of the global.
  • In build_slab's oxide branch (models/structure.py, metal_type == 'oxide'), add a termination sanity printout after building: composition of the top 3 atomic planes (reuse the gap-clustering helper _z_plane_clusters from models/surface_graph.py). Mixed-composition planes ⇒ nonpolar (good); alternating pure-cation/pure-anion planes ⇒ polar (warn loudly).
  • Determine the correct primitive-basis indices for NiO(100): build trial slabs with the (0,1,1) permutations, run the step-2 printout, and pick the one showing mixed Ni+O planes. Alternatively bypass the ambiguity: for rock-salt oxides let spglib return the conventional cell (spglib.standardize_cell instead of find_primitive) and use plain (1,0,0).
  • Set NiO's miller in METAL_CONFIGS, re-enable it in Parts 1–2, and validate: build_surface_graph(metal_type='oxide') on the relaxed slab should show a mixed top plane with both Ni_atop/O_atop ontop sites and NiO_bridge sites (the geometric enumerator, already implemented, handles it from there).
  • Acceptance: smoke-level Section A on NiO(100) produces sites, and the top-plane printout confirms nonpolar termination.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions