Random structure generation

Generate ensembles of amorphous structures by constrained random sequential placement with automated minimum separation distances derived from Shannon ionic radii.

How it works

Atoms are placed sequentially into a cubic cell. Each atom must satisfy pair-specific minimum interatomic distances computed automatically from Shannon ionic radii and bonding-type classification. No manual parameter tuning is required.

Automated minsep

For each element pair, the bond type is classified and the appropriate radii are used:

Bond type

Radii source

Scale factor

Example

Ionic (M-O, M-Cl)

Shannon ionic (CN-aware)

0.80

In-O: (0.80+1.40)*0.80 = 1.76

Metallic (M-M)

Metallic radii

0.85

Al-Al: (1.43+1.43)*0.85 = 2.43

M-M in oxide

max(metallic, sqrt(2)*d(M-O)*0.85)

cap 2.80

In-In: max(2.84, 2.64) = 2.80

Metalloid (Si-Si) in oxide

max(metallic, sqrt(2)*d(Si-O)*0.85)

cap 2.80

Si-Si: max(1.99, 2.12) = 2.12

Small anion (O-O)

Shannon ionic

0.80

O-O: (1.40+1.40)*0.80 = 2.24

Large anion (Cl-Cl)

Shannon ionic

0.70

Cl-Cl: (1.81+1.81)*0.70 = 2.53

When --target-cn is provided, CN-specific Shannon radii are used (e.g. Si CN=4: 0.26 A vs CN=6: 0.40 A), giving tighter minsep values.

Bond-type classifier

The classifier uses an element-type rule (nonmetal / metalloid / metal membership) with a Pauling electronegativity refinement: when the type rule would call a pair “ionic” but the Pauling Δχ is below 1.0, the pair is reclassified as covalent. This catches predominantly-covalent compounds whose Shannon ionic radii would otherwise give unrealistically small distances:

Pair

Δχ

Type rule

Final class

Why it matters

Ga–As

0.37

ionic (metal+metalloid)

covalent

Shannon radii would give minsep ≈ 0.68 Å — atomic overlap

In–P

0.41

ionic

covalent

III–V semiconductor

Si–C

0.65

ionic

covalent

Carbide

B–N

1.00

ionic

ionic (at threshold)

Sits right on the cutoff; Shannon radii give reasonable BN minsep

Ga–N

1.23

ionic

ionic

Stays ionic

Li–F

3.00

ionic

ionic

Stays ionic (clearly ionic)

The Δχ refinement is applied to the metalloid–nonmetal, metalloid–metal, and metal–nonmetal branches. The metallic branch (metal–metal) and the pure-covalent branch (nonmetal–nonmetal, metalloid–metalloid) are unaffected because the type rule already gives the correct answer there. The 1.0 threshold is empirical — it cleanly separates III–V/II–VI semiconductors and carbides (covalent character ≥ 70% by Pauling’s formula) from the polar-ionic borderline cases (GaN, ZnO, BeO) where Shannon ionic radii give sensible minsep values.

The bond classifier is exposed as amorphgen.utils.radii.classify_bond(sym_a, sym_b) for inspection.

Citations. The electronegativity scale follows Pauling’s original definition from bond-dissociation energies (Pauling 1932) as standardised in his textbook (Pauling 1960), with the specific numerical values used in AmorphGen taken from Allred’s 1961 thermochemical revision — the values now in the CRC Handbook and most chemistry textbooks. References:

  • Pauling, L. J. Am. Chem. Soc. 54, 3570–3582 (1932) — original EN derivation.

  • Pauling, L. The Nature of the Chemical Bond, 3rd ed., Cornell Univ. Press (1960) — textbook scale.

  • Allred, A. L. J. Inorg. Nucl. Chem. 17, 215–221 (1961) — revised values used in the code (PAULING_EN table in amorphgen/utils/radii.py).

Edge cases at the classifier boundary

The Δχ = 1.0 threshold sits exactly where chemistry genuinely gets ambiguous — bonds with Δχ in the ~0.85–1.15 band have mixed ionic/covalent character. Testing the 50-system of validation set, 54 of 55 cation–anion pairs (98%) agree between the per-pair Pauling classifier and the per-composition material-class radii bucket. The disagreement, and a few other compounds outside the 50-set that sit at the boundary, are listed below:

System

Pair

Δχ

Material class expects

Pauling rule says

Reality

MgH₂

Mg–H

0.89

ionic (hydride)

covalent

Rutile structure — predominantly ionic

MnS

Mn–S

1.03

covalent (chalcogenide)

ionic

α-MnS is rocksalt — ionic-leaning

TiC

Ti–C

1.01

covalent (carbide)

ionic

Rocksalt interstitial carbide — mixed bonding

BN

B–N

1.00

ionic (nitride)

ionic (stays — strict <)

Sits exactly on cutoff

These disagreements are benign: the bond classifier governs which radii produce the per-pair minsep, while the material classifier governs which radii produce the density estimate. The two answer different questions, and any modest inconsistency at the boundary is absorbed by the subsequent MLIP relaxation. If you generate one of these systems and the auto-derived density looks off (typically ±15–20% from experiment), set --target-density explicitly to bypass the auto path for that composition.

Automated density

Cell volume is estimated automatically:

Material class

Method

Packing factor

Group IV, pnictide, chalcogenide, carbide, boride, alloy

Elemental density * 0.80

Covalent oxide (SiO2, GeO2, B2O3)

Shannon CN=6 sphere packing

0.50

Metal oxide (In2O3, TiO2, Al2O3)

Shannon CN=6 sphere packing

0.52

Halide (Li2ZrCl6, NaCl, LiF)

Shannon CN=6 sphere packing

0.58

Nitride (AlN, GaN, Si3N4)

Shannon CN=6 sphere packing

0.52

Hydride (LiH, MgH2)

Shannon CN=6 sphere packing

0.55

Use --target-density for more accurate results when the experimental density is known.

Coordination-aware placement (optional)

With --target-cn, atoms are placed near under-coordinated sites within a bonding shell, producing structures with better short-range order. Disable with --no-sc (legacy flag name).

Transparency: the auto-derive log line

Every --random-gen run writes a single one-line summary at the top of random_gen.log capturing every chemistry-informed decision the auto chain made — so you can see why a particular minsep / density / target CN was used without reading the code. Example for Ga₂O₃:

[auto-derive] Ga16O24 → metal_oxide, OS{Ga:+3}, CN{Ga:5}, minsep{Ga-Ga:2.43 metallic | Ga-O:1.62 ionic Δχ=1.63 | O-O:2.24 anion-pack}, ρ=4.44 g/cm³ L=8.25 Å

Each field:

Field

What it means

Ga16O24 metal_oxide

Composition routed to the metal_oxide material class

OS{Ga:+3}

Cation oxidation state inferred from charge balance against the anion

CN{Ga:5}

Target coordination auto-detected per cation

minsep{pair:value class [Δχ=val]}

Per-pair: bond class + Pauling Δχ (shown only when the ionic classification is at stake) + minsep value in Å

ρ=… g/cm³  L=… Å

Auto-estimated mass density and cubic cell length

The line is grep-friendly: grep "auto-derive" random_gen.log retrieves it as a single line per generation run. Bond classes shown are ionic, covalent, metallic, and anion-pack (same-element nonmetal pairs use a separate anion-packing scale factor — see “Bond-type classifier” above).

CLI examples

# Formula format (In2O3 * 16 formula units = 80 atoms)
amorphgen --random-gen --composition "In2O3*16" --n-structures 20

# Atom count format (equivalent)
amorphgen --random-gen --composition In=32,O=48 --n-structures 20

# With target CN and density
amorphgen --random-gen --composition "SiO2*16" --n-structures 20 \
    --target-cn Si=4,O=2 --target-density 2.2

# With relaxation
amorphgen --random-gen --composition "In2O3*8" --n-structures 10 \
    --relax --model mace-mpa-0 --cell-filter none

Python API

from amorphgen import generate_random, batch_random

# Single structure (auto minsep, auto density from Shannon radii)
atoms = generate_random(
    composition={"In": 16, "O": 24},   # atom counts (Python API)
    seed=42,
)

# Batch generation (20 structures of SiO2)
paths = batch_random(
    composition={"Si": 16, "O": 32},
    n_structures=20,
    target_density=2.2,                 # optional, auto if omitted
    target_cn={"Si": 4, "O": 2},       # optional, auto if omitted
)

Note: The Python API takes atom counts as a dict. The CLI also accepts formula format: --composition "SiO2*16" is equivalent to {"Si": 16, "O": 32}.

Accessing radii data

from amorphgen.utils.radii import get_ionic_radius, classify_bond, default_minsep

# Shannon ionic radius
get_ionic_radius("In", cn=6)   # 0.80 A
get_ionic_radius("In", cn=4)   # 0.62 A

# Bond classification
classify_bond("In", "O")       # "ionic"
classify_bond("Si", "Si")      # "covalent"

# Auto minsep for a composition
ms = default_minsep(["In", "O"], target_cn={"In": 4})
# {"In-In": 3.11, "In-O": 1.72, "O-O": 2.24}

See Random structure generation for the full API reference.