Site Vectors (Force, Magmom, Spin)

Structures can carry per-site vector data in their properties dict. Recognized keys include force, magmom, spin and prefixed variants like force_DFT or magmom_MLFF. When multiple vector keys are present, each gets its own color, toggle, and per-key scale slider.

  • Fe BCC — single force

    Single force key, element-colored arrows

  • Fe BCC — antiferromagnetic magmoms

    Scalar magmom ±2.2 μB along z, spin-direction coloring (red=up, blue=down)

  • Fe BCC — canted spins

    Non-collinear spin vectors tilted off-axis

  • NaCl — ionic forces

    Forces on a rock-salt structure with different element colors per sublattice

  • TiO₂ rutile — force comparison

    force_DFT vs force_MLFF on a multi-element oxide. Use Origin Gap to separate overlapping arrows

  • Fe BCC — forces + magmoms

    Three vector layers: force_DFT, force_MLFF, and magmom with distinct directions. Per-layer palette coloring

  • BaTiO₃ 3×3×3 supercell — 135 atoms

    Large perovskite supercell with randomized force vectors on every atom

  • TiO₂ rutile — spins + forces

    Combining spin vectors on Ti atoms with force vectors on all atoms

<script lang="ts">
  import { Structure } from 'matterviz'

  const fe_bcc = {
    matrix: [[-1.435, 1.435, 1.435], [1.435, -1.435, 1.435], [1.435, 1.435, -1.435]],
    pbc: [true, true, true],
    a: 2.486,
    b: 2.486,
    c: 2.486,
    alpha: 109.47,
    beta: 109.47,
    gamma: 109.47,
    volume: 11.82,
  }
  const nacl = {
    matrix: [[5.64, 0, 0], [0, 5.64, 0], [0, 0, 5.64]],
    pbc: [true, true, true],
    a: 5.64,
    b: 5.64,
    c: 5.64,
    alpha: 90,
    beta: 90,
    gamma: 90,
    volume: 179.41,
  }
  const tio2 = {
    matrix: [[4.594, 0, 0], [0, 4.594, 0], [0, 0, 2.959]],
    pbc: [true, true, true],
    a: 4.594,
    b: 4.594,
    c: 2.959,
    alpha: 90,
    beta: 90,
    gamma: 90,
    volume: 62.44,
  }

  const examples = [
    {
      title: `Fe BCC — single force`,
      desc: `Single force key, element-colored arrows`,
      structure: {
        lattice: fe_bcc,
        sites: [
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Fe`,
            properties: { force: [0.8, -0.5, 1.2] },
          },
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [0.718, 0.718, 0.718],
            label: `Fe`,
            properties: { force: [-0.8, 0.5, -1.2] },
          },
        ],
      },
    },
    {
      title: `Fe BCC — antiferromagnetic magmoms`,
      desc:
        `Scalar magmom ±2.2 μB along z, spin-direction coloring (red=up, blue=down)`,
      structure: {
        lattice: fe_bcc,
        sites: [
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Fe`,
            properties: { magmom: [0, 0, 2.2] },
          },
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [0.718, 0.718, 0.718],
            label: `Fe`,
            properties: { magmom: [0, 0, -2.2] },
          },
        ],
      },
    },
    {
      title: `Fe BCC — canted spins`,
      desc: `Non-collinear spin vectors tilted off-axis`,
      structure: {
        lattice: fe_bcc,
        sites: [
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Fe`,
            properties: { spin: [1.5, 0.8, 1.8] },
          },
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [0.718, 0.718, 0.718],
            label: `Fe`,
            properties: { spin: [-1.2, 1.0, -1.6] },
          },
        ],
      },
    },
    {
      title: `NaCl — ionic forces`,
      desc:
        `Forces on a rock-salt structure with different element colors per sublattice`,
      structure: {
        lattice: nacl,
        sites: [
          {
            species: [{ element: `Na`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Na`,
            properties: { force: [0.3, 0.1, -0.5] },
          },
          {
            species: [{ element: `Cl`, occu: 1 }],
            abc: [0.5, 0.5, 0],
            xyz: [2.82, 2.82, 0],
            label: `Cl`,
            properties: { force: [-0.2, 0.4, 0.3] },
          },
          {
            species: [{ element: `Na`, occu: 1 }],
            abc: [0.5, 0, 0.5],
            xyz: [2.82, 0, 2.82],
            label: `Na`,
            properties: { force: [0.1, -0.6, 0.2] },
          },
          {
            species: [{ element: `Cl`, occu: 1 }],
            abc: [0, 0.5, 0.5],
            xyz: [0, 2.82, 2.82],
            label: `Cl`,
            properties: { force: [-0.3, 0.2, -0.4] },
          },
        ],
      },
    },
    {
      title: `TiO₂ rutile — force comparison`,
      desc:
        `force_DFT vs force_MLFF on a multi-element oxide. Use Origin Gap to separate overlapping arrows`,
      structure: {
        lattice: tio2,
        sites: [
          {
            species: [{ element: `Ti`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Ti`,
            properties: {
              force_DFT: [0.1, -0.2, 0.8],
              force_MLFF: [0.12, -0.18, 0.75],
            },
          },
          {
            species: [{ element: `Ti`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [2.297, 2.297, 1.480],
            label: `Ti`,
            properties: {
              force_DFT: [-0.1, 0.2, -0.8],
              force_MLFF: [-0.15, 0.25, -0.82],
            },
          },
          {
            species: [{ element: `O`, occu: 1 }],
            abc: [0.305, 0.305, 0],
            xyz: [1.401, 1.401, 0],
            label: `O`,
            properties: {
              force_DFT: [0.4, 0.4, -0.1],
              force_MLFF: [0.38, 0.42, -0.08],
            },
          },
          {
            species: [{ element: `O`, occu: 1 }],
            abc: [0.695, 0.695, 0],
            xyz: [3.193, 3.193, 0],
            label: `O`,
            properties: {
              force_DFT: [-0.4, -0.4, 0.1],
              force_MLFF: [-0.35, -0.45, 0.15],
            },
          },
        ],
      },
    },
    {
      title: `Fe BCC — forces + magmoms`,
      desc:
        `Three vector layers: force_DFT, force_MLFF, and magmom with distinct directions. Per-layer palette coloring`,
      structure: {
        lattice: fe_bcc,
        sites: [
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Fe`,
            properties: {
              force_DFT: [0.6, -0.3, 0.2],
              force_MLFF: [0.55, -0.28, 0.18],
              magmom: [0, 0, 2.2],
            },
          },
          {
            species: [{ element: `Fe`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [0.718, 0.718, 0.718],
            label: `Fe`,
            properties: {
              force_DFT: [-0.6, 0.3, -0.2],
              force_MLFF: [-0.65, 0.35, -0.25],
              magmom: [0, 0, -2.2],
            },
          },
        ],
      },
    },
    {
      title: `BaTiO₃ 3×3×3 supercell — 135 atoms`,
      desc: `Large perovskite supercell with randomized force vectors on every atom`,
      structure: (() => {
        // BaTiO3 perovskite: 5 atoms/cell × 3×3×3 = 135 atoms
        const lat_a = 4.01
        const basis = [
          { elem: `Ba`, frac: [0, 0, 0] },
          { elem: `Ti`, frac: [0.5, 0.5, 0.5] },
          { elem: `O`, frac: [0.5, 0.5, 0] },
          { elem: `O`, frac: [0.5, 0, 0.5] },
          { elem: `O`, frac: [0, 0.5, 0.5] },
        ]
        const n_rep = 3
        const super_a = lat_a * n_rep
        const sites = []
        // seeded pseudo-random for reproducible vectors
        let seed = 42
        const rand = () => {
          seed = (seed * 1103515245 + 12345) & 0x7fffffff
          return seed / 0x7fffffff - 0.5
        }
        for (let ix = 0; ix < n_rep; ix++) {
          for (let iy = 0; iy < n_rep; iy++) {
            for (let iz = 0; iz < n_rep; iz++) {
              for (const { elem, frac } of basis) {
                const abc = [
                  (frac[0] + ix) / n_rep,
                  (frac[1] + iy) / n_rep,
                  (frac[2] + iz) / n_rep,
                ]
                const xyz = [abc[0] * super_a, abc[1] * super_a, abc[2] * super_a]
                sites.push({
                  species: [{ element: elem, occu: 1 }],
                  abc,
                  xyz,
                  label: elem,
                  properties: { force: [rand() * 0.8, rand() * 0.8, rand() * 0.8] },
                })
              }
            }
          }
        }
        return {
          lattice: {
            matrix: [[super_a, 0, 0], [0, super_a, 0], [0, 0, super_a]],
            pbc: [true, true, true],
            a: super_a,
            b: super_a,
            c: super_a,
            alpha: 90,
            beta: 90,
            gamma: 90,
            volume: super_a ** 3,
          },
          sites,
        }
      })(),
    },
    {
      title: `TiO₂ rutile — spins + forces`,
      desc: `Combining spin vectors on Ti atoms with force vectors on all atoms`,
      structure: {
        lattice: tio2,
        sites: [
          {
            species: [{ element: `Ti`, occu: 1 }],
            abc: [0, 0, 0],
            xyz: [0, 0, 0],
            label: `Ti`,
            properties: { force: [0.1, -0.15, 0.3], spin: [0.5, 0.5, 0.8] },
          },
          {
            species: [{ element: `Ti`, occu: 1 }],
            abc: [0.5, 0.5, 0.5],
            xyz: [2.297, 2.297, 1.480],
            label: `Ti`,
            properties: { force: [-0.1, 0.15, -0.3], spin: [-0.5, -0.5, 0.8] },
          },
          {
            species: [{ element: `O`, occu: 1 }],
            abc: [0.305, 0.305, 0],
            xyz: [1.401, 1.401, 0],
            label: `O`,
            properties: { force: [0.3, 0.3, -0.05] },
          },
          {
            species: [{ element: `O`, occu: 1 }],
            abc: [0.695, 0.695, 0],
            xyz: [3.193, 3.193, 0],
            label: `O`,
            properties: { force: [-0.3, -0.3, 0.05] },
          },
        ],
      },
    },
  ]
</script>

<ul class="vector-grid">
  {#each examples as { title, desc, structure } (title)}
    <li>
      <h3>{title}</h3>
      <p>{desc}</p>
      <Structure {structure} scene_props={{ show_bonds: `never` }} />
    </li>
  {/each}
</ul>