Command-line reference ====================== The package installs five commands via ``[project.scripts]``. ``mag4-magnetic --help`` (and the others) show every option organised in titled groups; this page documents the concepts and the most-used flags. .. list-table:: :header-rows: 1 :widths: 28 72 * - Command - Underlying module * - ``mag4-magnetic`` - :func:`mag4.cli.fourstate.main` * - ``mag4-extract`` - :func:`mag4.cli.extract.main` * - ``mag4-magnon`` - :func:`mag4.cli.magnon.main` * - ``mag4-angles`` - :func:`mag4.cli.bond_angles.main` * - ``mag4-moments`` - :func:`mag4.cli.extract_moments.main` ``mag4-magnetic`` ----------------- Generation pipeline: parse CIF/POSCAR, detect J shells, build the isolation-aware supercell, deduplicate the spin configurations under the magnetic grey group (crystal symmetry + time reversal), then write per-config input directories for the chosen DFT code(s). Mode A — from a CIF (recommended): .. code-block:: bash mag4-magnetic --cif POSCAR_alpha-Gd2S3.cif --element Gd mag4-magnetic --cif POSCAR_alpha-Gd2S3.cif --element Gd \ --cutoff 7.0 --supercell 2 1 1 Mode B — from a POSCAR + manual couplings: .. code-block:: bash mag4-magnetic --poscar POSCAR --species 1 \ --couplings "J1:3.94,J2:5.88" Method selection (``--method``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 24 76 * - ``--method`` - What is generated * - ``four-state`` (default) - the targeted ``uu/dd/ud/du`` configurations per bond and the per-bond difference formulas (divisor :math:`4M`) * - ``energy-mapping`` - *every* inequivalent collinear order of the supercell, for a global least-squares fit; ``--jring`` adds the four-spin ring-exchange column * - ``16-state`` - the 16 plaquette flips (symmetry-reduced) for the exact parity projection of :math:`J_\mathrm{ring}` alone ``mag4-extract`` auto-detects the method from the report, so the post-processing command is identical in all three cases. Reference bath (``--ref-*``, mutually exclusive) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The probed atoms are flipped over a fixed spin background (default: FM, all +1). ``--ref-couplings "J1:AFM"`` builds an antiferromagnetic bath by signed 2-colouring (recommended for strong antiferromagnets — the SCF converges to the intended state far more readily); ``--ref-kvector "1/2 1/2 0"`` derives it from a propagation vector; ``--ref-magmom "32*0 1 1 1 -1 … 64*0"`` takes it *verbatim* as the supercell MAGMOM string (POSCAR atom order, ``n*v`` repetitions, non-magnetic zeros validated). Diagnostics ~~~~~~~~~~~ * ``--jring`` / ``--jprime`` (four-state) — print how much the ring term and beyond-cutoff shells leak into each extracted J, ending with a corrected-J formula. Both checks are free (no extra DFT, no change to the generated inputs) and therefore run **by default**: the J′ scan reaches the larger of 2×``--cutoff`` and the shortest lattice translation (``--jprime R`` overrides), and the ring check silently skips lattices with no square plaquette. Opt out with ``--no-jring`` / ``--no-jprime``. * ``--check-degeneracy`` (all methods) — keep the configurations that only time reversal proves degenerate as separate DFT runs; ``mag4-extract`` verifies :math:`|\Delta E|` per pair. * Every configuration is labelled with its space group **and** its magnetic (Shubnikov) group — BNS number, type, magnetic point group. DFT-code selection (``--code``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. list-table:: :header-rows: 1 :widths: 18 82 * - ``--code`` - Files written in each ``configN/`` * - ``vasp`` (default) - ``POSCAR`` + ``INCAR`` + ``KPOINTS`` * - ``wien2k`` - ``POSCAR`` + ``configN.inst`` + ``configN.struct`` in each ``configN/``, **plus** ``job.init`` and ``job.run`` driver scripts at the compound (parent) directory. The WIEN2k ``case == basename(pwd)`` convention applies. * - ``both`` - All of the above For WIEN2k modes, ``case.inst`` is generated by piping the spin pattern (translated to ``u/d/n``) into the WIEN2k ``instgen -ask`` script. The script is auto-detected via ``$WIEN2k_INSTGEN``, ``$PATH``, ``$WIENROOT/instgen_lapw``, then ``~/bin/instgen``. Override with ``--instgen PATH`` if needed. Symmetric struct generation (default) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, ``configN.struct`` is written using ``spglib`` so each spin configuration carries the highest space-group symmetry compatible with the cell that ``mag4-magnetic`` built. Atoms are coloured by spin direction (magnetic up, magnetic down, non-magnetic = bare element) and the detected orbits become one inequivalent block per Wyckoff site (``MULT > 1`` where applicable), with the full rotation/translation table written into the trailing symmetry block. Every orbit still receives a unique ```` label so WIEN2k does not merge chemically-similar but inequivalent sites. Because the same spglib analysis is used to generate ``configN.inst``, the per-orbit ``u/d/n`` answers fed to ``instgen`` are in lockstep with the struct file — no reordering needed on disk. Pass ``--no-symmetrize-struct`` to fall back to the legacy "every atom inequivalent, identity-only symmetry block" output (useful if a particular configuration trips up spglib). The ``--symprec E`` flag controls the distance tolerance handed to spglib (default ``1e-3`` Å). Per-config cell reduction (``--reduce``, opt-in) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default every ``configN.struct`` keeps mag4's one working supercell, so all configs share strictly identical cell and numerics — the safer choice recommended by the WIEN2k authors, and the one that makes a direct reduce-vs-no-reduce comparison possible. With ``--reduce``, each ``configN.struct`` is instead rewritten in the **standardized conventional cell** of its spin-decorated structure so the multiplicities written match the parent space group's standard Wyckoff table. For NiO ``config4`` (the dd of the axial J) the 16-atom 1×1×2 working supercell collapses to the 8-atom Pm-3m cubic primitive with ``MULT=[1, 3, 3, 1]`` and lattice letter ``P``; the all-FM ``config1`` collapses to the Fm-3m cubic *conventional* cell with lattice letter ``F`` and ``MULT=[1, 1]`` — per the WIEN2k user's guide §4.3, only one of every four F-centred atoms is listed in the struct, the others being generated by the ``F`` lattice letter. The WIEN2k lattice letter is taken from the SG symbol's first character with two conventional remappings: * international ``I`` (body-centred) → WIEN2k ``B`` * international ``A`` / ``B`` / ``C`` (base-centred) → WIEN2k ``CYZ`` / ``CXZ`` / ``CXY`` For an orbit on a centred lattice mag4 emits only one atom per centring coset (using spglib's ``mapping_to_primitive`` to identify them), so ``MULT`` in the struct file is the orbit size **divided by the centring factor** (4 for F, 2 for B / CXY / CYZ / CXZ, 3 for R, 1 for P / H). ``init_lapw``'s ``sgroup`` / ``symmetry`` pipeline accepts the struct without rewriting the Bravais lattice (which used to mismatch the listed ops). Configs whose colored structure has no extra symmetry beyond the working supercell stay at the supercell size. ``four_state_report.dat`` now records a per-config ``Cell: a=… | b=… | c=… | … | n_atoms=N | … | SG=#N (symbol)`` line under each ``Config #N`` block. ``mag4-extract`` reads those values and rescales each contributing config's total energy to the **least-common-multiple (LCM)** atom count of the four configs of each J before applying the four-state formula: .. code-block:: text E_X(in N_LCM cell) = E_X(in N_X primitive) × (N_LCM / N_X) J = ( E_uu' + E_dd' − E_ud' − E_du' ) / 4 ← E' are rescaled values This is exact because DFT total energy is **extensive** — scaling a primitive cell to a *k*-multiplied supercell scales the total energy by the same factor *k*. The J values come out identical to what you would get if every config had been computed in a single common cell. When ``mag4-extract`` detects mixed cell sizes it announces: .. code-block:: text INFO: Per-config cell metadata found: 5 configs span 3 distinct atom counts [2, 8, 16] — energies will be rescaled to per-J LCM cells. ``--no-reduce`` names the default explicitly (every config in the one working supercell, no rescaling involved). Driver scripts ``job.init`` / ``job.run`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Together with the per-config inputs, ``mag4-magnetic`` drops two tcsh helper scripts at the compound (parent) directory — siblings of ``config1/``, ``config2/``, … — so the post-mag4 workflow on the WIEN2k machine is just: .. code-block:: bash cd MyCompound/ ./job.init # setrmt + init_lapw -sp -prec 2n -noreduc -nohdlo -nokshift # create a .machines file for parallel execution, then: ./job.run # runsp -p -ec 1e-6 -cc 1e-5 in each configN/, then 'save' The scripts follow P. Blaha's recommended workflow: * ``setrmt`` sets the real muffin-tin radii (the values mag4 writes into the struct files are placeholders); tune per element there, e.g. ``setrmt -a Cu:2.1,O:1.7``. * ``init_lapw`` carries ``-numk -1 `` with ``--kspacing × 0.529177`` (Å⁻¹ → bohr⁻¹), so the WIEN2k k-mesh matches the VASP one. * When ``sgroup`` proposes an origin-shifted struct (``init_lapw`` exit status 3), the script pauses for an interactive check — accept only if the lattice type and atom count are unchanged (sgroup may e.g. reduce P → CXY, which would change the cell the report's energy formulas refer to). * With ``--functional PBE+U``, the ``init_orb -orb`` heredoc is generated **active** with ``element ℓ U J`` filled from ``--ldaul``/``--ldauu``/``--ldauj``, and ``job.run``'s ``runsp`` carries ``-orb``. ``init_orb`` reads U and J in **Rydberg**, so the eV flag values are divided by 13.605693122994 (``--ldauu 6 --ldauj 0.5`` → ``0.44099`` / ``0.03675``); a comment above the heredoc echoes both the eV input and the Ry output. ``ℓ`` is a quantum number and is passed through unchanged, and the VASP ``INCAR`` path keeps ``LDAUU``/``LDAUJ`` in eV. Both scripts are written ``chmod +x`` on POSIX. The remaining project-specific flags (``-ec``, ``-cc``, the ``save`` name, …) are inlined verbatim with comments — review in place before launching. Pass ``--no-job-scripts`` to skip them. The translation is sign-based per atom in POSCAR order: .. code-block:: text MAGMOM = -7 2*7 -7 3*7 4*0 → d u u d u u u n n n n (``+`` → ``u``, ``−`` → ``d``, ``0`` → ``n``). Geometry-aware J shells (``--ligand``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default J shells are grouped only by M–M distance. This lumps together pairs that share a distance but route super-exchange through different bridging geometries — e.g. on CuO the d ≈ 2.9 Å shell contains *both* edge-sharing pairs with two Cu–O–Cu bridges at ~96° *and* non-bridged pairs at the same distance. Pass ``--ligand X`` to split such shells into sub-shells (``J1a``, ``J1b``, …) using the bridging-angle fingerprint produced by :mod:`mag4.analysis.bond_angles`: .. code-block:: bash mag4-magnetic --cif CuO.cif --element Cu --cutoff 6.0 --ligand O Companion knobs: * ``--bond-cutoff R`` — max M–L distance (Å) for a ligand to count as bridging (default ``2.5``). * ``--angle-tol DEG`` — tolerance for grouping M–L–M angles and M–L–L–M dihedrals into the same fingerprint (default ``1.0``). * ``--ll-cutoff R`` — max L–L distance (Å) for an M–L–L–M super-super-exchange path (default ``3.0``). Used **only** for pairs with no direct M–L–M bridge; ``0`` disables the fallback. * ``--signed-dihedral`` — keep the IUPAC sign of M–L–L–M dihedrals in ``[-180°, +180°]``. Off by default (dihedrals are folded to ``|θ| ∈ [0°, 180°]`` so chiral mirror-image paths merge — the right choice for plain Heisenberg J). Switch on when Dzyaloshinskii–Moriya / antisymmetric exchange matters. A pair's fingerprint is a 4-tuple ``(n_bridges, sorted bridge-angle bins, n_dihedrals, sorted dihedral bins)``. Pairs with a direct M–L–M bridge keep the dihedral slot empty so they are not over-split. Pairs with no direct bridge fall back to their M–L–L–M dihedral fingerprint. When ``--ligand`` is supplied the magnetic-sublattice symmetry operations are additionally filtered to keep only those that preserve each pair's fingerprint, so :func:`mag4.spinconfig.find_unique_configs` does **not** merge configurations from physically distinct sub-shells. Expect more unique configurations than the same run without ``--ligand``. ``mag4-extract`` ---------------- Post-processing CLI: walks the ``configN/`` subdirectories of a compound directory, checks every DFT calculation converged, parses the total energies (``TOTEN`` for VASP, ``:ENE`` for WIEN2k), and applies the extraction recorded by ``mag4-magnetic`` in ``four_state_report.dat`` — four-state difference formulas, energy-mapping least squares (with error bars, ``--couplings`` / ``--drop-couplings`` model restriction, ``--check-mag`` magnetic-state gating), or the 16-state ring projection; the method is auto-detected. Built-in checks printed on every run: per-config **convergence**, **band gap / metallicity** (WIEN2k reads the global ``:GAP (global)`` line), converged **moment vs Sz**, and — after ``--check-degeneracy`` — the time-reversal degeneracy :math:`|\Delta E|` table. The complete screen output is persisted to ``/mag4_extract.out``. .. code-block:: bash cd MyCompound/ # contains configN/ + four_state_report.dat mag4-extract --code vasp # JS² in eV / meV mag4-extract --code vasp --spin 3.5 # also adds J in meV and K mag4-extract --code wien2k --spin 3.5 # WIEN2k campaigns that save several runs side by side (save_lapw): mag4-extract --code wien2k --scffile pbe # reads configN/pbe.scf mag4-extract --code wien2k --scffile r2scan # reads configN/r2scan.scf The same J table is also written to ``/j_values.dat``. For WIEN2k, ``mag4-extract`` also prints a per-config verification table with the last ``:DIS`` (charge distance) and ``:ENE`` (total energy in Ry) it parsed, so the user can confirm the SCF converged to the desired tolerance. Convergence rules (coarse, code-agnostic): .. list-table:: :header-rows: 1 * - Code - File scanned - Convergence flag * - ``vasp`` - ``configN/OUTCAR`` - OUTCAR ends with ``Voluntary context switches:`` AND no ``WARNING: NELM was reached`` warning * - ``wien2k`` - ``configN/configN.scf`` - At least one ``:ENE`` is present AND it falls inside the **last** ``:ITE…:`` iteration block Tighter convergence (``EDIFF`` / ``EDIFFG`` / ``:CONV`` thresholds) is **not** enforced — the right value is project-specific. Diagnostics (NELM hit, file truncated, last ``:CONV`` value, …) are surfaced in the per-config notes so the user can make the call. Exit codes: * ``0`` — every J shell in the report was successfully computed. * ``1`` — at least one J shell could not be computed (one of its 4 contributing configs is missing or did not converge). * ``2`` — hard error (compound dir not found, report file missing, …). ``mag4-magnon`` --------------- Multi-sublattice linear spin-wave theory, T_c (MF + Tyablikov RPA), optional magnon dispersion. Give the couplings by exactly one of: * ``--JS2 "J1:0.26,…"`` — the **fitted** :math:`JS^2` values, exactly as mag4-extract prints them (native input, used as-is); * ``--J "J1:1.04,…"`` — the **bare** :math:`J = JS^2/S^2` (the ``J(meV)`` column); multiplied by :math:`S^2` internally, conversion logged; * ``--from-extract DIR`` — read ``j_values.dat`` directly (couplings *and* spin; non-OK rows skipped; shell labels verified against the CIF). .. code-block:: bash mag4-magnon --cif Gd2O2S.cif --element Gd \ --JS2 "J1:0.26,J2:0.26,J3:0.12,J4:0.01,J5:0.39" --spin 3.5 \ --plot --kpath "Gamma M K Gamma A L H" # straight from mag4-extract, ring exchange folded into effective # couplings (LSWT mapping, provenance recorded in the report): mag4-magnon --cif La2CuO4.cif --element Cu --from-extract La2CuO4/ --jring Two guards keep the temperatures honest: the **Mermin–Wagner dimensionality check** (a network that is not 3D yields an energy scale, not a Néel/Curie temperature; a coupling counts as zero only when the fit cannot resolve it from zero — :math:`|JS^2| < 2\sigma` of its error bar or below the fit RMS — with ``--j-significance`` as manual override) and the **flat-axis q₀ diagnostic** (ordering-vector components along dispersion-flat axes are reported as undetermined). ``mag4-angles`` --------------- For each detected J shell, compute every M-L-M angle of bridging ligands. The ``--ligand`` option accepts a comma-separated list (e.g. ``S,O``). .. code-block:: bash mag4-angles --cif Gd2S3.cif --element Gd --ligand S mag4-angles --cif Gd2S3.cif --element Gd # auto-detect ligands ``mag4-moments`` ---------------- Read converged magnetic moments from a tree of WIEN2k calculation directories. .. code-block:: bash mag4-moments # interactive mag4-moments 9 16 # atoms 9-16, auto-detect dirs mag4-moments 9 16 AF-J1ud AF-J2dd # explicit directories