Skip to content

Feature/phonon reporting - #20

Open
alinzh wants to merge 14 commits into
masterfrom
feature/phonon-reporting
Open

Feature/phonon reporting#20
alinzh wants to merge 14 commits into
masterfrom
feature/phonon-reporting

Conversation

@alinzh

@alinzh alinzh commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator
  1. Add phonon processing
  2. Add actual Vultr pricing

alinzh added 14 commits August 4, 2026 21:41
…e overrides

- Add bare-metal plans (vbm-*) to CLOUD_PRICING from Vultr API
- Add detect_provider() vbm token, read_provider_and_machine_type_from_config()
- Add --provider, --engine, --machine-type CLI flags to dft-report-aiida/dft-report
- Rename hetzner_rate->cloud_rate, cost_eur->cost, add currency field
- provider+machine_type fallback: CLI flag -> /etc/yascheduler/yascheduler.conf -> skip
- When no provider info available (no flag, no config), cost columns are omitted from CSV
- --engine filter skips expensive FLEUR enrichment (Seebeck/displacement)
- Remove dead code in pricing.py (duplicate lines after return)
- 62 tests: bare-metal rates, config read, skip_cost, provider/engine/machine_type overrides

Closes #17
All tasks complete (62 tests pass, verified on real AiiDA data).
Moved to openspec/changes/archive/2026-08-04-add-vultr-cost-calculation/
- Fix amd5 substring collision: longest-key-first matching in get_cloud_rate
- Unknown provider/plan returns None instead of 0.0 (no silent 'free' cost)
- UpCloud recognised in config but has no pricing → rate/currency None
- resolve_provider_and_rate(): single shared helper, validates provider+machine_type
  consistency (no cross-cloud mixing, e.g. vultr+ccx13 → rate None)
- Remove skip_cost: auto-detect from computer name still works without config
- Currency set even when rate is None (provider known, plan unknown)
- Config tests use tmp_path (no /etc/yascheduler/ dependency)
- Engine filter tests verify QueryBuilder.append() gets process_type filter
- 81 tests: amd5, cross-provider mismatch, unknown plans, no-config auto-detect

Addresses PR #19 review feedback.
… integration

Merge CRYSTAL phonon parsing from PR #18 with FLEUR phonon WorkChain
enrichment and thermodynamic integration (ZPE, F, S, Cv) from
ab_initio_calculations.phonon_thermo.

CRYSTAL (from PR #18):
- crystal_parser/properties/phonon.py: parse phonon frequencies from
  OUTPUT MODES block, PHONON.DAT, FREQ.DAT
- _enrich_crystal_extras: has_phonons, phonon_freq_min/max/mean/std,
  phonon_n_imag, phonon_modes_count
- determine_calc_type_summary: phonon/transport/elastic/electron types
- --calc-type, --max-duration, --skip-displacement CLI flags

FLEUR (new):
- phonon_utils.py: extract frequencies from PhonopyFleurWorkChain via
  phonopy force_constants, integrate via custom/phonopy/ase methods
- _enrich_phonon_data: enrich phonon CalcJobs by walking provenance to
  parent PhonopyFleurWorkChain
- n_imaginary, zpe_kjmol, f_at_t_kjmol, s_at_t_jkmol, cv_at_t_jkmol,
  phonon_n_qpoints, phonon_n_bands, t_eval columns
- dft-report-phonons CLI: standalone phonon table with PR, SG, Pearson,
  formula, cell params, cost, thermodynamic properties
- --phonon-t-eval, --phonon-method CLI flags

Shared:
- structures.py: get_space_group_robust, nullify_right_angles
- _pearson_from_attrs: Pearson symbol filling in _enrich_with_structure_fast
- resolve_provider_and_rate (Vultr+Hetzner) replaces get_cloud_rate/get_cost
  in AiiDA-DB pipeline
- ab_initio_calculations dependency for phonon_thermo integration
dft-report-phonons now queries both FLEUR PhonopyFleurWorkChain nodes
and CRYSTAL phonon CalcJobNodes, producing a unified phonon table.

CRYSTAL phonon frequencies are parsed from the retrieved OUTPUT file
(MODES block), grouped into q-points, and integrated via the same
thermodynamic methods (custom/phonopy/ase) as FLEUR.

New functions:
- extract_frequencies_from_crystal_calc(): parse OUTPUT → freqs cm⁻¹
- get_crystal_phonon_summary(): full summary for CRYSTAL phonon CalcJob
- scan_phonon_workchains() now queries both WorkChainNode + CalcJobNode

Added 'engine' column to distinguish fleur/crystal in the phonon CSV.
Added CRYSTAL phonon columns (has_phonons, phonon_freq_min/max/mean/std,
phonon_n_imag, phonon_modes_count) to _PHONON_CSV_COLUMNS.

Fixed: label filter for CRYSTAL phonon query (AiiDA QueryBuilder does
not support 'like' on label column — post-query filtering instead).
Main report (dft-report-aiida) now adds only two phonon columns:
- phonon_pk: PK of the phonon calculation (WorkChain for FLEUR, CalcJob for CRYSTAL)
- has_phonon: boolean flag

Full thermodynamic properties (ZPE, F/S/Cv, n_imaginary, etc.) are
available via the standalone dft-report-phonons CLI.

Removed phonon_t_eval, phonon_method, phonon_mesh parameters from
scan_aiida_calculations, generate_aiida_reports, and report_aiida_cli.
Priority for space_group filling:
1. Label (e.g. 'ZnO/186: Phonon frequencies' -> 186) — conventional SG
2. mpds_query.sgs — conventional SG from MPDS
3. spglib on StructureData — only if label/mpds have no SG

Previously spglib ran first on the primitive cell (phonopy supercell)
and gave wrong conventional SG (e.g. P1 instead of P-3m1 for ZnO/186).
Now label is parsed in initial summary, before any spglib enrichment.

Also fixed _sgs_from_workchain_label to strip trailing ':' from tokens
(e.g. '186:' in 'ZnO/186: Phonon frequencies [1]').

Removed pearson from main report (_SUMMARY_CSV_COLUMNS) — it was
computed on the primitive cell and gave wrong values. Pearson remains
available in dft-report-phonons standalone CLI.
FLEUR WorkChain labels (e.g. 'MgO/225 - phonons') and CRYSTAL labels
(e.g. 'ZnO/186: Phonon frequencies [1]') contain the conventional space
group number. Now parsed first, with spglib on the structure as fallback.

Fixes: MgO showed SG=160 (rhombohedral primitive) instead of 225 (Fm-3m),
KNbO3 showed 160 instead of 221 (Pm-3m), ZnO showed 1 instead of 186.
Full report: removed has_phonons, phonon_freq_*, phonon_n_imag,
phonon_modes_count, cloud_rate — keeping only phonon_pk + has_phonon
for phonon rows.

Phonon report: removed has_phonons, phonon_freq_*, phonon_n_imag,
phonon_modes_count, cloud_rate — these were CRYSTAL-specific and
redundant with n_imaginary/n_qpoints/n_bands.

Fixed FLEUR cost/currency/duration: WorkChainNode has no computer,
so _find_remote_computer() walks children to find the yascheduler
computer. All 19 phonon rows now have cost/currency/duration filled.
…lumns

FLEUR PhonopyFleurWorkChain nodes are now added as separate rows in
the main report with calc_type='phonon', engine='fleur'. This replaces
the phonon_pk/has_phonon columns — phonon calculations are simply rows
like scf/optimise/transport.

Removed phonon_pk and has_phonon from _SUMMARY_CSV_COLUMNS and
_null_summary_keys.

_enrich_phonon_data -> _enrich_phonon_computer: only fills
computer/cost/currency for FLEUR phonon rows (WorkChainNode has no
computer, so _find_remote_computer walks children to find yascheduler).

Fixed _formula_from_label to handle labels without ':' (e.g.
'ZnO/186 - phonons' -> 'ZnO' via '/' fallback).
Reordered _SUMMARY_CSV_COLUMNS and _PHONON_CSV_COLUMNS for readability:
identity fields first (formula, pk, uuid, calc_type, engine, SG),
then metadata (label, date, computer, exit), then results (duration,
cost, bandgap, energy, etc.), then cell params last.
scan_calculations now returns (summary_store, error_dict_crystal,
error_dict_fleur, phonon_store) — 4 values. archive_and_save expected
only 3, causing ValueError in aiida-mpds-monitor archive generation.

Fix: use *_ to absorb the extra phonon_store.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant