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_ENtable inamorphgen/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 |
|---|---|
|
Composition routed to the |
|
Cation oxidation state inferred from charge balance against the anion |
|
Target coordination auto-detected per cation |
|
Per-pair: bond class + Pauling Δχ (shown only when the ionic classification is at stake) + minsep value in Å |
|
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.