Changelog
The full release history is maintained in CHANGELOG.md at the repository root
and included verbatim below.
Changelog
Notable changes to IRMA. Format follows Keep a Changelog; versions follow Semantic Versioning.
[Unreleased]
- Mode-0
iel=10input files give the other species' partial phonon spectra per temperature, as Card 12e right after Card 12 in each temperature block, instead of once as Card 6e after Card 6d. Each species' Bragg-edge Debye-Waller factor at a temperature now comes from that temperature's spectrum, as the principal's already came from its own Cards 11-12; a negative temperature reuses the previous block's spectra with the rest of the block. A spectrum for the principal, a species change between blocks, and spectra left after Card 6d are refused with messages that say where the spectra go. An input file moved to the new layout gives a byte-identical tape; values change only where a later block supplies a different spectrum (MF7/MT2 at that temperature). The MLIP emitter, the GUI import and export, the help texts and the input reference follow the new layout. In the GUI the principal's spectrum is always the DOS on the form, so an imported spectrum for the principal is not written. - Coherent elastic (MF7/MT2) at later temperatures: the Bragg edges are
thinned at the first temperature, as in NJOY, and each later block adds
the last kept edge once for every dropped edge. When some edge
contributes more at a later temperature, as with a stiffer spectrum
given for it, that overstated the later blocks (85% on a test case). The
writer now keeps the edges such a temperature needs and adds each edge
once. Files in which no edge contributes noticeably more at a later
temperature are unchanged, and
docs/njoy.mdlists this as a deliberate difference from NJOY.
[1.1.0] — 2026-09-24
This release comes out of a full review of the code. Most of the changes
are internal and leave every output as it was: the irma package is about
9,200 lines shorter, and after each step the outputs of 24 reference cases
were compared with those of the code before the review. The classic LEAPR
kernels still reproduce the NJOY2016 reference tapes byte for byte in MF7.
Outputs that change, and what to regenerate:
- ENDF tapes: the MF1/MT451 record of every tape (EMAX, the library version and release, and the default header lines). MF7 changes only in the cases listed under ENDF evaluations. Regenerate a tape to get the new header.
- Modes 1 and 2: the MT4 effective temperature, by about 3e-5 relative.
- Mode-2 tapes and NCrystal packs of materials with more than one species: the coherent one-phonon part of each species' table, which now adds up to the material's exact total. Regenerate them.
- ENDFTSL packs: reconvert them. The graphite inelastic cross section drops 4.2% at 25 meV, and packs grow by up to 19 times.
- NCrystal exports: the NCMAT Debye temperatures rise (graphite 827 K to 923 K at 296 K), and with them the Bragg planes the plugin uses. Single-species packs are unchanged. Re-export to update them.
- MLIP bundles: the DOS is a histogram of the phonon modes. Re-emit inputs from existing bundles; rebuild a bundle to refresh its own DOS file.
- Spectra: the bins near the ends of the energy axis change, and so do the chopper width on the energy-gain side, the kf/ki factor on 2-D maps, mode-0 runs whose DOS comes from phonopy, and runs with a minimum phonon energy.
Security
- The phonopy.yaml guard refuses every YAML tag and
%TAGdirective. Percent-escaped tags (!!%70ython/...), verbatim tags (!<tag:yaml.org%2C2002:python/...>), a%TAGline after a UTF-8 byte-order mark, and UTF-16 files used to pass the guard and reach phonopy's unsafe YAML loader, which runs the code such a tag names. The error quotes the refused line. phonopy writes none of these forms, and every phonopy.yaml in the repository and in the reference bundles still loads.
ENDF evaluations
- MF1/MT451: EMAX is the MF7/MT4 upper energy B(4), as NJOY2016.79 writes
it, instead of 0.0. NVER and LREL (library version and release: 8 and 1
for ENDF/B-VIII.1) are optional trailing fields on Card 4, after
iint, with defaults 8 and 1, where they were fixed at 6 and 0. When comment cards 3–5 are blank, the writer fills in the standard ENDF/B thermal header lines (----ENDF/B-VIII.1 MATERIAL mat,-----THERMAL NEUTRON SCATTERING DATA,------ENDF-6 FORMAT); a deck that gives its own lines keeps them. - The three
examples/tsldecks carry an IRMA example header on comment card 1, blank cards 2–5, and their description from card 6. Two of them started their free text on card 1, where it filled the structured header fields, andgraphite_iel10_classic.inputcarried the NCSU ENDF/B-VIII.0 header and description word for word. examples/tsl/graphite_mode2.input, the production mode-2 graphite deck, usesiint=1(lin-lin) on grids from the automatic generators: 399 α × 541 β, was 200 × 426. The tape grows from 2.7 MB to 6.2 MB.- Mode 2, materials with more than one species: each species' tape and
pack gets the fraction |F_p|² / Σ_g |F_g|² of each mode's coherent
one-phonon total |Σ_g F_g|² (
coherent_partition_mode: principal-share). Both sums run over each set of degenerate modes, so the split does not depend on the eigenvectors the eigensolver returns. The old split gave a species its own |F_p|² plus a share of each interference term 2 Re(F_p F_o*) in proportion to the coherent cross sections. That share can be negative, the writers set negative cells to zero, and the summed material law came out too high. On the BeO fixture at 296 K, 0.9% of the Be cells and 5.2% of the O cells were negative, and the per-Q zeroth moment of the sum was 1–4% high between 0.3 and 1.5 Å⁻¹. The new shares add up to a whole-cell run to 2e-16. Each species' own table changes more than the sum: its per-Q moment moves by −38% to +22% (O) and −17% to +13% (Be) at low Q, while its integral over the whole range moves by 0.2%. Single-species materials such as graphite and Be, modes 0 and 1, MT2 and the spectra model are unchanged. - Modes 1 and 2: the per-atom DOS behind the MT4 effective temperature is a histogram of the mesh modes, each weighted by |e|², instead of a Gaussian as wide as two grid steps, which put weight below the lowest mode. The effective temperature moves by about 3e-5 relative (fast graphite test: 707.2952 K to 707.2741 K).
- A principal split over several Card 6d rows is merged in every mode. The
merge ran only for inelastic modes 1 and 2, so an
iel=10deck in mode 0 that listed the principal on two rows counted its coherent comb twice. One-row decks are unchanged. - Directional Debye-Waller tensors are rotated into the frame of the Bragg comb (a along x, b in the xy-plane) when the phonopy lattice is oriented differently; they were applied in the model's own Cartesian frame, on the wrong axes. For ENDF MT2 the rotation applies only when Card 6c describes the phonopy cell (lengths within 1e-3 relative, angles within 0.01°); otherwise a NOTE line says the tensors are used as given, because Card 6c may describe another cell. Models already in the standard orientation, which includes every shipped example, are unchanged.
- The short-collision-time tail in
sintdivides by the square root of 4π·wt·α·T̄, so the Gaussian integrates to 1; NJOY2016 leaves out the square root (leapr.f90:1892). docs/njoy.md lists this as a deliberate divergence. Only the discrete-oscillator and cold-hydrogen kernels reach the tail, past the tabulated β range, and the golden decks and NJOY minitapes stay byte-identical. - The multiphonon energy-coverage warning for modes 1 and 2 now compares
the reach of the truncated sum, the order times the highest phonon
energy, with the recoil ridge at the largest Q plus six thermal widths,
instead of with the top of the energy grid. The old comparison fired for
heavy atoms at orders that already converge the sum, where the grid top
lies far out on a negligible tail. Any order that meets the automatic
order rule passes the new check, so it fires only for a lower order; the
metadata gains
needed_multiphonon_beta_support. The check on the computed S(α,β) array uses the same needed reach: it warns only when the array goes to zero before it, instead of whenever it goes to zero below the grid top. - Modes 1 and 2 print the lowest kept mesh-mode energy and how many output energies lie below it, since the one-phonon term is zero there; docs/modes.md and docs/grids.md explain this.
- Force constants embedded in phonopy.yaml take precedence over an explicit FORCE_CONSTANTS or FORCE_SETS file (phonopy's rule). Every phonopy path now prints a warning naming the unused file. The docs had said the explicit file wins.
- The deck reader refuses:
- a numeric card with an empty comma field (
,,or a leading comma). NJOY keeps that item at its default, while IRMA dropped it and moved every later value one field left. - Card 10 temperatures that do not increase. THERMR reads the MT4 temperatures in order, and the coherent-elastic edge thinning uses the first one, so a descending list gave wrong data above the first temperature.
- a non-ASCII character in a comment card, which shifted the fixed MAT/MF/MT columns of its MF1 record. Tapes are written as ASCII.
- a minimum phonon energy that removes every mode, such as a Card 6g
missing its
mpdirfield (200 /), which reads as a 200 meV cutoff card.
- a numeric card with an empty comma field (
- Run metadata:
one_phonon_energy_jacobian_meV_per_THzis renamedone_phonon_meV_per_THz(the value is a unit factor, not a Jacobian), andcoherent_diagonal_termsays whether thecoherent_diagonalarrays hold the per-site self term or the principal group's |F_p|².
Neutron-scattering spectra
- Resolution broadening works on a padded grid. S is computed past both
ends of the energy axis by the kernel's reach (6σ for a Gaussian; for a
Lorentzian, until 1e-3 of its area lies outside), convolved and then
cropped, and each kernel column and the elastic line are normalized over
the whole uniform grid instead of over the window. Each line shape used
to be rescaled to sum to 1 inside the window, so intensity that belonged
past an axis end was pushed back in: at
e_min = 0the full elastic line stayed on the axis, and the last bins belowe_maxwere scaled up. The 1-D spectra and the 2-D map now follow one convention. The E = 0 elastic value halves ate_min = 0, bins within about 15 meV ofe_maxchange by up to 40%, and interior bins change by a median of 4e-7. A spectrum no longer depends on wheree_maxlies (2e-7; it was 23% at the last bin). - Chopper resolution evaluates the energy-gain side at its own final energy. Every gain-side transfer had been given the elastic width. For ARCS-100-1.5-AST at 300 Hz and Ei = 30 meV the FWHM is 1.04 meV at E = 0 and 2.24 meV at E = −30 meV. The loss side is unchanged.
physics.kinematic_kf_kiapplies to 2-D maps too, per energy column before the elastic line and the resolution pass, and the map metadata records it. Before, it weighted only the 1-D spectra.- The minimum phonon energy reaches the cached engine context. The context was built with a cutoff of 0, so its mode data ignored the cutoff: for graphite in mode 1 with a 30 meV cutoff, 20% of the intensity stayed below 30 meV.
- The mode-0 phonopy bridge uses the per-atom DOS histogram described under
ENDF evaluations. The Gaussian biased the Debye-Waller λ upward: on the
graphite fixture's 12³ mesh at 300 K, λ goes from 1.153 to 0.891,
against 0.894 from the exact mode sum.
examples/spectra/data/graphite_C_dos.txtis regenerated. - The CNCS and LET chopper packages are named High-Flux, after the PyChop settings their widths come from; they were Standard (CNCS) and High-Resolution (LET). The widths are unchanged. There are no aliases, so configs with the old names need editing.
start:stop:stepangle ranges end atstop(0:1:0.6gave 0, 0.6, 1.2), and a step whose sign points away fromstopis an error instead of an empty list. The GUI uses the same parser.- Config validation catches five mistakes before the engine runs: a
mode-1/2 species other than C without
b_coh_fmandsigma_inc_b(the engine has built-in values only for carbon); numbers read as strings, since YAML 1.1 loads2e2as a string; a chopper setting that does not transmit Ei, a frequency above the instrument maximum, or an unknownchopper_speckey; angles other than the vision preset's 45° and 135° banks, which the 1-D path ignored and the map used; and a mode-0 species DOS that does not start at ω = 0. - CLI:
--set KEY=VALUEworks withvision,indirectanddirectand replaces six undocumented flags (--force-constants,--force-sets,--elastic-from-tape,--bank-halfwidth,--combine,--components) and the unused flag-form--q-max. Config errors in the flag form exit with status 2, as in the config form; they exited with 3.
NCrystal export and plugins
- The NCMAT
debye_tempplaceholder reproduces the engine's mean-squared displacement in NCrystal's full Debye model, found by bisection. It used the high-temperature limit, which drops the zero-point term. At 296 K the reference exports move from 827 K to 923 K (graphite C), 1107 K to 1351 K (BeO Be) and 959 K to 1113 K (BeO O); the packs are unchanged. The value matters in both modes: withelastic: falseNCrystal's own elastic uses it, and withelastic: trueNCrystal's |F|² cutoff, computed from it, chooses the Bragg planes whose structure factors the plugin computes from the pack's tensors. Coherent elastic through the plugin changes by up to 0.4% on graphite and 5e-5 on BeO. - The exporter uses
material.force_constantsandmaterial.force_sets. It accepted both keys and then read the files next to phonopy.yaml. Embedded force constants still win, with a warning, and the pack provenance records the name and SHA-256 of the file actually used (force_constants_name,force_constants_sha256). - The exporter refuses a cell with |cos α − cos β cos γ| > 1e-9, such as an FCC or BCC primitive cell. NCrystal 4.4.6's general lattice branch (NCLatticeUtils.cc:75-78) builds a wrong reciprocal lattice for these cells and misplaces every Bragg plane. Use the conventional cell; the check can go once NCrystal is fixed.
- ENDFTSL converter: NCrystal interpolates S linearly in β, so every log-linear (INT=4) β interval of a tape is subdivided into n = ceil(max|ln(S_{j+1}/S_j)| / sqrt(8·tol)) parts, with tol = 1e-3. On the graphite example the inelastic cross section drops 4.2% at 25.3 meV (2.2% at 1 meV and at 0.1 eV), and BeO and Al2O3 drop 0.2–0.3%. From 1 meV to 0.5 eV graphite now agrees with a direct integration of the tape's own law to 0.04%, where it was 0.5–5.5% high. Packs grow 4.5 to 19 times (graphite 2.0 MB to 37 MB, PMMA at 20 K 7.8 MB to 65 MB), and loading the graphite pack takes 7.3 s instead of 1.3 s. Lin-lin (INT=2) intervals are left as they are; see Known limitations.
- ENDFTSL converter: S values go into the pack straight from the stored table. The exp(+β/2)·exp(−β/2) round trip overflowed for LAT=1 tapes below about 41 K (PMMA at 20 K failed with OverflowError) and moved about a third of the values by 1 ulp.
- ENDFTSL converter: a sole coherent carrier (a hydride whose metal alone
scatters coherently, or an IRMA SEF tape) is scaled by its atom
fraction. The
per_atomchoice overstated its Bragg edges by 1/f, and the default refused to convert. Thecoherent_conventionkey is removed; a config that sets it is an error. - ENDFTSL converter: LASYM=1 tapes (LEAPR writes them for cold H2 and D2)
are refused; they converted into packs NCrystal could not load. A
single-tape conversion needs
--symbol,--massand--density: the old defaults (C, 12.0107, 1 g/cm³) described any tape as carbon. - Both plugins build with
BUILD_WITH_INSTALL_RPATH, so installing copies the library unchanged. On macOS the install step deleted the build-tree RPATH withinstall_name_tool, which invalidates the linker's code signature unless that tool re-signs the library (conda's does, Apple's does not). macOS then killed any process that loaded the plugin, with exit 137 at the firstcreateScatter; a pip build with CMake 4.4 on arm64 did this. Rebuild a plugin that fails this way. - Plugin versions:
ncrystal_plugin_ENDFTSLis 0.3.0, for the converter changes above. Its__version__, its CMake project and the pack's converter stamp had said 0.0.1 while pyproject.toml said 0.2.0; all of them now carry one version, and a test checks that they agree. The CMake project ofncrystal_plugin_IRMAis 0.6.0, as in its pyproject.toml.
MLIP front end
- User-trained MACE checkpoints.
--potential maceormace-offwith--model <file>(the GUI's model field gains a Browse... button) loads the checkpoint in the parent process and pins its absolute path into the calculator specification that every displacement worker and force server rebuilds from. The manifest records the file's SHA-256 with the model class, cutoff, interaction layers, element table and head. If the checkpoint does not cover every element in the structure, the build stops before relaxation and names the missing elements; the same check applies to the named MACE models. Multi-head checkpoints are refused, and float32 weights are evaluated in float64. The force-cache fingerprint version is now 2, so the scratch caches of interrupted builds from earlier versions are recomputed. - The bundle's total DOS and the species DOS in emitted inputs are a
histogram of the phonon modes, the same one the engine uses. A flat band
counts in full, and the Gamma translations and imaginary modes are left
out. phonopy's tetrahedron DOS gave a flat band zero width, so it fell
back to a 1 meV Gaussian, and a Gamma-only disordered DOS kept the three
translations as a smeared peak at 0. On the reference bundles the
Debye-Waller λ of the disordered box goes from 146.4 to 3.75, and that of
the crystal rises by 2%. All DOS files share one grid: 0 to the highest
mode, at least 200 points, spacing at most 0.5 meV.
--dos-smearingis removed. - The THz-to-meV factor comes from
irma.core.constants. The bundle code used an older CODATA value, 5e-7 lower, so bundle DOS energies, census frequencies and emitted spectra move by 5e-7 relative. irma mlip emitrefuses--min-phonon-energyfor the mode-0 deck and for disordered bundles, whose files do not apply it. The value had been dropped without a message.irma mlip emitprints the phonon mesh the emitted inputs use (int(98/a)+1 points per axis) next to the bundle's--mesh, which sets only the quick-look DOS and census mesh.- SevenNet: the fidelity (
modal="mpa") is passed whenever the model is 7net-mf-ompa or 7net-omni. Naming either one with--modelfailed with "modal argument missing". The manifest records the modal. irma mlip build --bornparses the BORN file with phonopy's own parser, so files with phonopy's# epsilon and Z* of atomsheader (written by phonopy-vasp-born and phonopy-qe-born) are accepted. The old count came out one row short and refused them.- A pinned pet-mad checkpoint found in the cache is checked against its
recorded SHA-256, a check the cache path had skipped. The force server
computes stress only when asked; for a checkpoint without stress, ASE
reran the whole model on every call.
irma mlip buildrejects a non-positive or non-finite--delta,--fmaxor--snap-symmetryand a negative--nmaxbefore any work. - The manifest's
argvrecords the command as given instead of the constantirma mlip, and a KeyError or TypeError message names its type.
GUI
- ENDF form: NVER, LREL and three HSUB fields (comment cards 3–5) with help, in the MF1 section.
- ENDF form: a phonopy
total_dos.datis resampled onto the zero-anchored grid with the file's spacing. phonopy's default range starts below 0, and the reader kept the file's own points, which shifted the whole DOS down by that offset. A--fmin=0file is used as it is. - Apply ZA moves an imported Card 6e spectrum with the atom row it relabels. Otherwise the engine refused the deck over a card the form does not show.
- Run and Save with a principal ZA that matches no atom row show the engine's message, which names Apply ZA, instead of offering to relabel the row.
- The atom block refuses extra positions and non-integral Z, A or npos,
which were dropped or truncated;
nprmust be an integer; a non-numeric bins-per-decade value is an error instead of turning grouping off. - Error dialogs show the whole message, and the runner keeps the last 4 output lines. It kept 12 and then cut them to the first 500 characters, which dropped the line with the error.
- MLIP panel: the minimum phonon energy is passed for every emit target, not only for endf.
- Neutron-scattering panel: the 2-D map is computed unmasked and masked only for viewing and export, so with the mask toggle off the cells outside the kinematic envelope are shown. On the Direct tab the mask checkbox starts unticked. It started ticked, so a fresh map with the tab's default width-polynomial resolution was masked to a detector-angle band the tab does not show.
- Neutron-scattering panel: Open keeps the config fields the panel has no
control for (
elastic_from_tape,q_pad_invA,bank_halfwidth_deg,combine), lists them in the log, and writes them back. Running or saving had reset them to their defaults. A map config for indirect or vision geometry is refused on Open with a pointer toirma spectra map, since the panel runs maps for direct geometry only.
Removed
irma mlip build --dos-smearing.- Spectra: the six flag-form options that
--setreplaces and the flag-form--q-max(see above), and theIRMA_JOBSandIRMA_NCPUenvironment overrides. - NCrystal export:
export.site_groups, which could only reorder the default one-group-per-species partition. A config that sets it fails with "unknown export key". - ENDFTSL converter:
coherent_convention(see above). coherent_partition_mode: principal-xs-weightedis nowprincipal-share(see ENDF evaluations), with no alias; a config that sets the old value is refused. The run metadata losesgroup_coherent_weightsandcoherent_interference_pair_weighting.- Python API:
irma.core.enginere-exports onlyrun_leapr,LeaprResult,DeckError,parse_leapr_inputandTokenReader.irma.ncrystalexports onlyNCrystalExportConfig,build_packs,write_packs,IRMAPack,read_packandwrite_pack, and thencrystal_plugin_IRMA.packre-export of the last three is gone.irma.spectrano longer hasfrom_irma_cache,gaussian_resolution,Q_fitorbank_bragg_lines. The noncubic engine's Gaussian line deposition (sigma_mev, and--sigma-mevon its diagnostic CLI) is gone; production runs always bin the lines.
Internal
- Code: duplicated paths are merged and dead branches and unused options removed in the engine, the ENDF writer, the spectra model, the NCrystal exporter, the MLIP front end and the GUI, with no output change. The engine and the GUI share one set of Card 6b–6g readers.
- Tests: duplicates, tests of removed code, and tests that pinned wording or history are removed, and the remaining docstrings state what each test checks. The CrysXT extinction gate tightens from 5e-3 to 1e-10, and a test pins the Skold correction against an NJOY2016 tape.
- Documentation: the pages were checked against the code and corrected where they had drifted.
Known limitations
- NCrystal evaluates S log-linearly in α (NCSABEval.cc instantiates only that form), while a lin-lin (INT=2) tape is linear in α. Through the ENDFTSL plugin, the inelastic cross section of such a tape falls below the tape's own law at low energy: on the mode-2 graphite example at 296 K it is low by 4.6%, 8.0%, 10.2%, 4.5%, 2.7% and 0.9% at 1 meV, 3 meV, 9.6 meV, 25.3 meV, 0.1 eV and 0.5 eV. THERMR processing of the same tape agrees with the law to 0.2%. The IRMA plugin passes its S(α,β) table through the same NCrystal evaluation, and this may account for part of the low-energy gap described in docs/ncrystal-plugin.md. Refining the α axis in the ENDFTSL converter, and checking the IRMA exporter's α spacing, may be necessary after this release. A prototype on the graphite tape brings the worst deficit to 0.9% with 2.6 times the α points (pack 4.3 MB to 11 MB) and to 0.33% with 4.8 times (20 MB).
[1.0.3] — 2026-09-16
- Minimum phonon energy for the phonopy-backed modes 1 and 2. An optional
one-value card before Card 6g (also
physics.min_phonon_energy_meVin spectra configurations and--min-phonon-energyon the spectra CLI,export.min_phonon_energy_meVfor the NCrystal exporter, andirma mlip emit --min-phonon-energy, with a field on each GUI form) removes every phonon mode with energy at or below the value from every term: the DOS, the Debye-Waller tensors, the coherent and incoherent one-phonon scattering, and the multiphonon expansion. Nothing replaces the removed modes. Blank or 0 keeps the automatic floors, which already exclude imaginary modes, so existing inputs are unchanged. The run log and the metadata (min_phonon_energy_meV,phonon_cutoff) report the removed weight and the change in the mean-square displacement, with a warning above 1%; NCrystal packs record the value in their provenance.
[1.0.2] — 2026-09-16
Lin-lin (iint=1) grids, the multiphonon work grid, and the GUI's
principal-scatterer handling. Log-lin (iint=0) grids are byte-identical
to 1.0.1; evaluations on uniform output grids are byte-identical; a
log-lin evaluation on an automatic grid whose phonon region is not 300
steps gets that region's own step as its multiphonon work spacing (third
item below).
- The lin-lin beta grid keeps its 0.5 step out to a margin past the
back-scatter alpha at the highest incident energy
(
linlin_fine_beta_limit:RIDGE_MARGIN_SIGMASwidths of the down-scattering kernel, with an upper bound on T_eff fromfreq_maxand the hottest temperature in the deck) instead of stopping at that alpha. Stopping there left populated cells on the coarse log tail, and lin-lin interpolation across them raised the graphite total cross section between 2 eV and the requested energy (0.8% for a 5 eV grid, 2.6% for a 10 eV grid, from the processed PENDF), while the same tape processed log-lin stayed flat; with the margin the rise is 0.09% (5 eV) and 0.10% (10 eV), the cost of the 0.5 step itself (calibration table in docs/grids.md). The wider fine region costs beta points (541 to 5 eV against 395 log-lin; 710 to 10 eV); the deck emitters, the GUI grid preview, and the NCrystal exporter print a line built from what was generated: the count, the log-lin count, the stored cap, and the energy the fine step reaches. - The lin-lin step cap is scaled by the deck's lowest temperature
(
evaluation_temperatures_K) because alat=1grid is stored in 0.0253 eV units: a 0.5 stored step evaluated at 77 K was a 1.9 physical step. A seam node that would print as a duplicate at the deck's six decimals is dropped. - The multiphonon work spacing for a non-uniform output grid is the output grid's own phonon-region step (the first run of at least ten equal spacings below the highest phonon energy), so the deck's phonon subdivision sets the multiphonon resolution and tail points cannot change it. The previous median rule coarsened from 0.67 meV to 12.7 meV when a graphite beta grid gained 235 tail points, which moved the cross section by 0.3% over 0.5 to 2 eV; it remains only for grids with no such run.
- GUI: choosing inelastic_mode 2 selects
iint=1(lin-lin), the form the coherent one-phonon law needs; modes 0 and 1 select log-lin. A deck import keeps the deck's owniint. - GUI: Apply ZA (the former "Fill AWR + sigma_free from ZA") also
relabels the atom row of the ZA's element to the same nuclide, taking
A,AWR,b_cohandsigma_incfrom the one table entry and keeping the positions, and reports the change on a line under the button. Until now "Fill structure from phonopy.yaml" left every row as the natural element and a principal ZA naming an isotope (6012) was refused by the engine, with nothing in the GUI to make the two agree. Only the button changes a row; a row carrying constants other than the table's is replaced only after a dialog, other elements and rows sharing the element are never touched automatically, and nuclides without usable constants are refused before any change. Run and Save make the same offer once more when the deck is still inconsistent. - The principal-scatterer membership rule and its message now live in one
place (
irma.core.crystal_input.principal_mismatch_message), used by the engine, the deck validator, and the GUI; the engine's error names the row it found and both ways to fix the deck.
[1.0.1] — 2026-08-20
Hardening of MLIP environment provisioning, from the first field reports. No physics or engine changes: evaluations are byte-identical to 1.0.0.
irma mlip env createnow runs a torch/NumPy interop probe after the import check, retries once withnumpy<2when a torch wheel built against NumPy 1.x is detected (Intel Macs: torch wheels stopped at 2.2.2), and refuses to register an environment thatpip checkreports inconsistent afterward.- Shared environments (mace/mace-off) import-check every sibling before registering any of them.
- Install failures keep the part of pip's output that names the irreconcilable requirements; dispatch errors carry a one-sentence hint for the known failure signatures.
- With uv on PATH, potential environments are pinned to Python 3.12; potential packages lag new interpreters. Intel Macs get an up-front note about the platform.
- The nequip-compile bootstrap guards a torch.export crash on bleeding-edge torch (mixed cuDNN TF32 flags); verified against torch 2.13 (CUDA build).
- Windows: the provisioned environment's interpreter path now points
at
Scripts\python.exe. - GUI help and manual updated to match, including the platform support note.
[1.0.0] — 2026-08-03
Initial public release. IRMA turns one phonon calculation into three outputs on one engine:
- ENDF-6 File 7 evaluations from LEAPR-style input files: the classic
kernels (validated bit-for-bit against NJOY2016 reference tapes),
generalized coherent elastic for arbitrary crystals (
iel=10, SEF/MEF output conventions, Bragg-edge grouping, opt-in crystalline extinction), and the phonopy-backed noncubic inelastic modes with the exact coherent one-phonon term, anisotropic Debye-Waller tensors, a per-species partition for polyatomic materials, and automatic alpha/beta grids. - Instrument-resolved neutron spectra (
irma spectra): indirect- and direct-geometry spectrometers, chopper resolution, 2-D S(Q,E) maps, and a DOS-driven mode 0. - NCrystal transport exports (
irma ncrystal) sampled by the companionncrystal_plugin_IRMA, plus the standalonencrystal_plugin_ENDFTSLplugin for sampling ENDF TSL files directly in NCrystal.
The MLIP phonon front end (irma mlip) builds the phonon calculation
itself from a bare crystal structure with one of nine pretrained
machine-learned interatomic potentials, and emits ready-to-edit
inputs for all three outputs (--inelastic-mode 0|1|2, mixed
elastic format by default).
A GUI (python -m irma --gui) drives every path. examples/ maps
sixteen runnable examples to their calculation types; skills/irma/
ships an opt-in assistant skill for AI coding agents; the validation
record under docs/validation/ documents the evidence behind the
physics (NJOY reference tapes, Euphonic and OCLIMAX cross-code
comparisons, and measured VISION, ARCS, and VENUS data).
The development history preceding this release is internal to ORNL.