Your first run#
This walkthrough goes from an empty directory to a screened crystal structure with an OPTIMADE record. It takes about a minute of compute. Every output below is real — only absolute paths have been shortened.
It assumes matmelt --version works (Installation) and that SMACT,
PyXtal and MACE are importable by some interpreter (The tool and the science stack).
1. Scaffold a config#
$ mkdir matmelt-demo && cd matmelt-demo
$ matmelt init
init writes a commented matmelt.yaml and immediately runs the environment
check against it, so you find out at once whether this machine can do the work:
Wrote starter config: matmelt.yaml
Edit run.elements and the backends/stages blocks for your machines; re-run
'matmelt doctor' after any change.
Checking the environment against it now:
...
│ compose │ smact │ python3 │ local │ ok │ smact importable │
│ structure │ pyxtal │ python3 │ local │ ok │ pyxtal importable │
│ screen │ mace │ python3 │ local │ ok │ mace importable │
│ extract │ stdlib only │ python3 │ local │ ok │ standard library │
│ │ │ │ │ │ only -- always │
│ │ │ │ │ │ ready │
└───────────┴─────────────┴─────────────┴───────┴────────┴─────────────────────┘
Seed enumeration: 2 element(s) -> 3 combination(s) (size 1: 2, size 2: 1).
doctor: all checks passed.
If any stage says MISSING, fix it before continuing — the command to run is
printed under the table.
2. Make three edits#
Open matmelt.yaml. The scaffold already targets sodium and chlorine, which is
what we want. Change three things:
run:
name: my-first-run
work_dir: ./materials-work
elements: [Na, Cl]
combination_sizes: [2] # binaries only, so this run stays small
pipeline:
stop_after: structure # stop after generating candidates
stages:
screen:
backend: laptop
options:
python: python3
device: cpu
model_size: small # ~32 MB; the default 'medium' is better science
combination_sizes: [2] narrows the seeds from three (Na, Cl, and Na–Cl) to
just the binary. stop_after: structure deliberately stops the run before
screening, so you can look at what was generated before spending compute on it.
model_size: small keeps the first model download small.
Check the edits:
$ matmelt doctor
doctor: all checks passed.
3. Generate candidate structures#
$ matmelt run --yes
Run my-first-run: compose -> structure
Seed enumeration: 2 element(s) -> 1 combination(s) (size 2: 1).
Seeded 1 combination(s); starting the drain loop.
pass 1: submitted=1
pass 2: expanded=1, children=1, submitted=1
pass 8: expanded=1, children=37
Materials by state
┏━━━━━━━━━━━━┳━━━━━━━┓
┃ State ┃ Count ┃
┡━━━━━━━━━━━━╇━━━━━━━┩
│ EXPANDED │ 2 │
│ STRUCTURED │ 37 │
└────────────┴───────┘
stop_after structure: stage drained; materials rest at its output, ready for the
next stage -- raise or remove stop_after (or use --only) to continue them.
About ten seconds. Read that summary carefully, because it shows the funnel’s shape:
One seed,
Cl-Na, went intocompose, which asked SMACT which charge-balanced compositions are plausible and produced one:Cl1Na1.That composition went into
structure, which asked PyXtal for a candidate crystal in each 3D space group and got 37 valid ones.The two parents are
EXPANDED— a terminal state meaning “this fanned out into children”, not a failure.The 37 candidates rest at
STRUCTURED. A mid-funnelstop_afteris a pause, not a retirement: they are live and claimable by a later run.
4. Look at what you have#
$ matmelt status --state STRUCTURED
Run my-first-run: 37 material(s) at STRUCTURED.
Materials at STRUCTURED
┏━━━━━━━━━━━━━━━┳━━━━━━━━┓
┃ Material ┃ Parent ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━┩
│ Cl1Na1_3D-1 │ Cl1Na1 │
│ Cl1Na1_3D-2 │ Cl1Na1 │
│ Cl1Na1_3D-3 │ Cl1Na1 │
│ Cl1Na1_3D-6 │ Cl1Na1 │
│ Cl1Na1_3D-10 │ Cl1Na1 │
...
Each id says what the material is: composition, dimensionality, and space-group
number. Cl1Na1_3D-221 is the candidate in space group 221, Pm-3m.
On disk, each material has its own directory:
$ ls materials-work/Cl1Na1_3D-221/
structure.cif structure.json
5. Screen one candidate#
Screening all 37 would take a few minutes. Push a single one through instead —
--materials restricts a run to the materials you name (and anything they fan
out into). First raise the stop stage so the run may go all the way:
pipeline:
stop_after: extract
$ matmelt run --materials Cl1Na1_3D-221 --yes
Run my-first-run: compose -> structure -> screen -> extract
Seed enumeration: 2 element(s) -> 1 combination(s) (size 2: 1).
foundation model (size=small) ready in ~/.cache/mace
--materials: no seed combination matched -- relying on materials already in the
store.
pass 1: submitted=1
pass 8: completed=1, submitted=1
pass 9: completed=1, finalized=1
Materials by state
┏━━━━━━━━━━━━┳━━━━━━━┓
┃ State ┃ Count ┃
┡━━━━━━━━━━━━╇━━━━━━━┩
│ DONE │ 1 │
│ EXPANDED │ 2 │
│ STRUCTURED │ 36 │
└────────────┴───────┘
--materials: the selected materials are settled; unselected materials were not
run.
About fifteen seconds: one MACE relaxation, then extraction into a record. The other 36 candidates are untouched and still waiting.
Note
--yes answers the model-download consent prompt in advance. Run without it and
MatMelt asks first, disclosing the size and the cache location; declining stops
the run cleanly rather than failing partway.
6. Read the result#
$ matmelt results
Results of run my-first-run:
Finished materials
┏━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┓
┃ Material ┃ Parent ┃ Record ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━┩
│ Cl1Na1_3D-221 │ Cl1Na1 │ yes │
└───────────────┴────────┴────────┘
1 DONE material(s), 1 with extracted record(s).
The material’s directory now holds the whole story:
$ ls materials-work/Cl1Na1_3D-221/
record.json relaxed.cif screen_result.json structure.cif structure.json
screen_result.json is the screening verdict — what was decided, and on what
evidence:
{
"category": "RELAXED",
"converged": true,
"n_steps": 5,
"final": {
"e_eV_atom": -3.2325740511589527,
"fmax_eV_A": 3.4855789502953297e-15,
"stress_max_GPa": 0.09507366185438959,
"volume_A3": 41.89601877227525,
"min_bond_A": 3.007841059579302
}
}
RELAXED means the relaxation converged and the relaxed cell passed the
physical sanity checks — bond lengths, residual stress, volume change and energy
all within bounds. A candidate that fails those gets FAILED with the reasons
listed, which is a result, not an error: the run continues and its exit code
stays 0.
relaxed.cif is the relaxed structure. record.json is the OPTIMADE-shaped
record — composition fields, lattice vectors, sites, and MatMelt’s own
provenance under _mcli:
{
"dimension": "3D",
"space_group": 221,
"space_group_symbol": "Pm-3m",
"lattice_type": "cubic",
"formula": "Cl1Na1"
}
To collect every finished record into one file:
$ matmelt results --export records.json
Exported 1 record(s) to records.json.
What you just did#
You ran a four-stage pipeline: SMACT proposed a composition, PyXtal generated 37 symmetry-constrained candidates, MACE relaxed one of them and judged it, and the extract stage turned the survivor into a portable record. Everything ran on your own machine, in a workspace you can inspect, resume or throw away.
The 36 untouched candidates are the natural next step: remove --materials and
run again, and MatMelt picks up exactly where it left off.
Next: Verify your install — a short checklist proving the install is sound. Then the tutorials, which widen the element set (T1), explain every config key (T2), and move the expensive stage onto another machine (T3).