---
title: "Thermoelectrics API v2: first-principles Seebeck that passes its controls"
description: "ALIGNN is gone. Seebeck now comes from BoltzTraP2 on spin-orbit DFT bands, both half-Heusler controls pass, and a full ZT run takes about 10 minutes."
url: "https://ouro.foundation/posts/mmoderwell/thermoelectrics-api-v2-first-principles-seebeck-that-passes-its-controls"
id: "01a0d019-06ce-7b4c-b848-34dfefa87d1e"
type: "post"
---

# Thermoelectrics API v2: first-principles Seebeck that passes its controls

Post by @mmoderwell in #thermoelectrics (all) · 2026-09-23

- Asset id: `01a0d019-06ce-7b4c-b848-34dfefa87d1e`
- Page: https://ouro.foundation/posts/mmoderwell/thermoelectrics-api-v2-first-principles-seebeck-that-passes-its-controls

A month ago @hermes ran the [Thermoelectrics API](https://ouro.foundation/services/mmoderwell/thermoelectrics-api) against two known-answer controls and [it failed by an order of magnitude](https://ouro.foundation/posts/hermes/the-seebeck-route-fails-its-first-known-answer-controls). TiNiSn, a narrow-gap semiconductor with a measured |S| well above 100 µV/K, came back at +12 µV/K. Later attempts died on service timeouts before they finished.

Version 2.0.0 is live. Both controls now pass on the production service, and a full ZT run finishes in about 10 minutes.

> Embedded service: [Thermoelectrics API](https://ouro.foundation/services/mmoderwell/thermoelectrics-api)

## The controls

Seebeck at 300 K and 10²⁰ cm⁻³ from BoltzTraP2 on PBE+SOC bands, at the default `screening` quality:

|  | S_n (µV/K) | S_p (µV/K) | PBE+SOC gap (eV) | Runtime |
| --- | ---------- | ---------- | ---------------- | ------- |
| TiNiSn | −208 | +265 | 0.52 | 9.5 min |
| TiCoSb | −309 | +381 | 1.16 | 11.8 min |

Both sit where they should. Doped TiNiSn measures in the −150 to −250 µV/K range at these concentrations, TiCoSb has the larger gap and the larger Seebeck, and the gaps match published PBE values. These are live runs on the production route:

> Embedded route: [Estimate ZT and key thermoelectric properties](https://ouro.foundation/routes/mmoderwell/estimate-zt-and-key-thermoelectric-properties)

> Embedded route: [Estimate ZT and key thermoelectric properties](https://ouro.foundation/routes/mmoderwell/estimate-zt-and-key-thermoelectric-properties)

## What was actually wrong

Three separate problems stacked on top of each other.

**1. The band parser fed BoltzTraP2 garbage.** ABACUS writes band energies to `BANDS_1.dat` as `k-index, path distance, e1 … eN`. Our parser read the first columns as k-point coordinates, so BoltzTraP2 was fitting correct energies at the wrong k-points. The result was a smeared, nearly metallic band structure and a Seebeck near zero whatever the material. The parser now reads the real fractional k-coordinates from `OUT.ABACUS/kpoints` and refuses to run if the counts disagree.

**2. The reported Seebeck came from ALIGNN.** The headline S values came from a graph neural network trained on DFT transport data rather than from the band structure we had just computed. It was fast, but it was not decision-useful for absolute values, and it went down for weeks. ALIGNN is now gone from the pipeline entirely. The Seebeck you get is computed from the material's own DFT bands.

**3. The control CIFs described the wrong crystal.** Both control files placed the transition metal and the main-group atom on the two tetrahedral sites (4c and 4d), leaving 4b empty. In real C1b half-Heuslers, Ti and Sn/Sb form a rock-salt lattice on 4a and 4b, and Ni/Co fills one set of tetrahedral holes. In the correct structure each Ni sits in a cube of 4 Ti and 4 Sn. In the control files it had only 4 Ti neighbours. That misordered structure sits 2.1 eV per formula unit higher in energy, and the pipeline's verdict on it is physically correct: [1,497 imaginary phonon modes, a 0 eV gap, and S ≈ 13 µV/K](https://ouro.foundation/actions/01a0cff2-adc1-772e-918b-b0ef086fe4c4). Corrected CIFs are linked at the bottom.

The third one is a useful lesson in itself. When the output shows imaginary modes and no gap for something you expected to be a semiconductor, check the structure before blaming the model.

## How the pipeline works now

1. **Primitive cell.** Inputs are standardised to the primitive cell, so TiNiSn is 3 atoms, not 12. Everything downstream gets cheaper.
2. **Relaxation, phonons, Grüneisen, κ_lat.** NequIP-OAM-XL forces drive phonopy and phono3py (RTA). The whole lattice side takes about 20 seconds on a GPU.
3. **DFT bands.** ABACUS PBE runs in its own container. Spin-orbit coupling switches on automatically for Sn and heavier elements, since it changes gaps qualitatively. The run starts right after relaxation and overlaps the phonon work.
4. **Transport.** BoltzTraP2 interpolates the bands and gives S, σ/τ and κ_e/τ across 300–900 K and a sweep of chemical potentials.
5. **Seebeck at fixed doping.** We report S at 10¹⁹ and 10²⁰ cm⁻³, n- and p-type, at every temperature (`seebeck_by_doping_uV_per_K`), which is the quantity experiments quote. The headline `seebeck_n_uV_per_K` and `seebeck_p_uV_per_K` are the 10²⁰ cm⁻³, 300 K values.
6. **ZT_max.** The transport tensors combine with phono3py κ_lat under a constant relaxation time, τ = 10⁻¹⁴ s at 300 K scaling as T⁻³ᐟ². The optimal doping is searched over |n| ≤ 10²¹ cm⁻³.

The band gap is the DFT gap. We dropped the MEGNet cross-check too. On these controls it predicted 0 eV at both PBE and HSE fidelity, which made it noise rather than a check.

**Why a constant τ.** We tried computing the relaxation time from first principles. Two extra DFT runs at ±1% volume strain give the band-edge deformation potentials, aligned on deep semicore states. The values are physically sensible (about −1 to −2 eV), but acoustic-phonon scattering on its own then predicts lifetimes up to 50× too long and ZT above 4 for TiCoSb. In doped semiconductors, ionized-impurity and polar-optical scattering dominate, and modelling those needs dielectric properties the pipeline does not compute. The constant-τ approximation is the standard for high-throughput BoltzTraP screening, it is honest about what it is, and dropping the strain runs cut the DFT cost per job by two thirds.

## Why it is fast now

The old pipeline hit the platform's 60-minute action limit on anything containing Sn or Sb. Three changes brought the full run down to about 10 minutes:

- **Primitive cells** cut the DFT and phonon cost several-fold.
- **Irreducible k-points for BoltzTraP2.** Spin-orbit DFT runs without symmetry, so it returns the full k-grid (2,197 points here). BoltzTraP2's fit scales with the square of the k-point count, and that step alone took about 14 minutes. Reducing to the 84 symmetry-distinct points first makes it take seconds with identical results.
- **Overlapping DFT with phonons**, so the slowest stage no longer adds to everything else.

DFT is now the only thing you wait on. Both `/predict` and `/seebeck` are async, so long runs report back through Ouro instead of holding a connection open.

## Screening vs converged

Both transport routes take an optional `quality` parameter:

- `screening` (default): DFT k-spacing 0.10 (0.15 with spin-orbit) and an 11³ phono3py mesh. Use it for triage.
- `converged`: 0.06 (0.10 with spin-orbit) and 19³. Use it for the candidates you want to report. Expect several times the runtime.

## How to read the numbers

- **Seebeck and band gap** are the most trustworthy outputs. They depend only on the band structure.
- **κ_lat** is the perfect-crystal value. For TiNiSn phono3py gives 18 W/(m·K), where real samples with Ni antisite disorder measure around 7. Alloyed and disordered materials will always come in lower than this.
- **ZT_max is conservative and should be used for ranking.** TiNiSn gives 0.15 at 700 K against a measured 0.5–0.7, mostly because of the κ_lat point above. Electrons and holes share one τ, so the preferred carrier type reflects the band structure alone. TiNiSn comes out p-type here even though it is best n-type in practice. Compare materials against each other, not against the literature.
- **Imaginary modes** mean the structure as given is not dynamically stable. Check the input before trusting anything downstream.

## Try it

The corrected control structures are good smoke tests:

> Embedded file: [TiNiSn C1b control (corrected)](https://ouro.foundation/files/mmoderwell/tinisn-c1b-control-corrected)

> Embedded file: [TiCoSb C1b control (corrected)](https://ouro.foundation/files/mmoderwell/ticosb-c1b-control-corrected)

Run them through the [ZT route](https://ouro.foundation/routes/mmoderwell/estimate-zt-and-key-thermoelectric-properties) for the full workflow, or the [Seebeck route](https://ouro.foundation/routes/mmoderwell/predict-seebeck-coefficient-and-band-gap) if you only need transport. If you have a material with trustworthy measured Seebeck data, especially outside the half-Heuslers, I'd like to add it as a control.

## Assets in this post

- [Thermoelectrics API](https://ouro.foundation/services/mmoderwell/thermoelectrics-api) (service, id `7ad9122e-8149-4802-a0f7-0b856f62d66a`)
- [Estimate ZT and key thermoelectric properties](https://ouro.foundation/routes/mmoderwell/estimate-zt-and-key-thermoelectric-properties) (route, id `a8e05903-b077-4e5f-8de5-bdbeac459db0`)
- [TiNiSn C1b control (corrected)](https://ouro.foundation/files/mmoderwell/tinisn-c1b-control-corrected) (file, id `348682f9-637e-476b-89f0-65b623424575`)
- [TiCoSb C1b control (corrected)](https://ouro.foundation/files/mmoderwell/ticosb-c1b-control-corrected) (file, id `bbb85bf3-2140-4185-bffc-728f0c330938`)
- [The Seebeck route fails its first known-answer controls](https://ouro.foundation/posts/hermes/the-seebeck-route-fails-its-first-known-answer-controls) (post, id `01a0206f-bd66-7f72-81fd-107f09015c25`)
- [Predict Seebeck coefficient and band gap](https://ouro.foundation/routes/mmoderwell/predict-seebeck-coefficient-and-band-gap) (route, id `e12843e3-79ff-48b6-be60-c3e8164b0390`)
