Skip to content

Fast X: level populations edition - #466

Open
nabobalis wants to merge 3 commits into
wtbarnes:mainfrom
nabobalis:speed_3
Open

Fast X: level populations edition#466
nabobalis wants to merge 3 commits into
wtbarnes:mainfrom
nabobalis:speed_3

Conversation

@nabobalis

@nabobalis nabobalis commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Test to see if Claude MD can speed up some code in this repo.
According to Claude (unverified), these are the speeds up.

    ┌───────────────────────────┬────────────────┬────────┐
    │ Case                      │ Original       │ Now    │
    ├───────────────────────────┼────────────────┼────────┤
    │ Fe XXIII two-ion (21T×9n) │ 73.5 s         │ 5.2 s  │
    ├───────────────────────────┼────────────────┼────────┤
    │ Ca XVIII two-ion          │ 74.3 s         │ 6.4 s  │
    ├───────────────────────────┼────────────────┼────────┤
    │ O VI default              │ 73.3 s         │ 6.9 s  │
    ├───────────────────────────┼────────────────┼────────┤
    │ Fe XII single-ion         │ 9.9 s          │ 3.4 s  │
    ├───────────────────────────┼────────────────┼────────┤
    │ Coupled n–T               │ 14.5 s         │ 1.4 s  │
    ├───────────────────────────┼────────────────┼────────┤
    │ proton_electron_ratio     │ ~39 s* / 1.4 s │ 0.38 s │
    └───────────────────────────┴────────────────┴────────┘

Now whether the code is good, is another question.

Avoid repeated expensive recomputation in the level populations
calculation while keeping the output bit-identical:

- Cache the Ion instances returned by next_ion()/previous_ion() for
  internal use so that rate matrices of the recombining ion are only
  computed once rather than on every density iteration.
- Cache the density-independent sum of the two-ion rate matrices.
- Memoize plasmapy atomic_number/atomic_symbol/element_name lookups,
  which construct an expensive Particle object on every call.
- Share the proton-electron ratio with the next ion since it only
  depends on temperature and the abundance/ionization datasets.

Benchmark (21 temperatures x 9 densities): Fe XXIII 73.5->7.2 s,
Ca XVIII 74.3->8.1 s, O VI 73.3->9.3 s, Fe XII (single-ion model)
9.9->5.0 s, coupled n-T 14.5->3.0 s.
Further speed up of the level populations calculation (and anything
else that creates many Ion instances or reads many datasets), again
keeping the output bit-identical:

- DataIndexerHDF5.__getitem__ now does the membership check, child
  indexer creation, and read with a single open of the HDF5 file
  instead of two to three opens per access.
- Memoize the set of available ion names and the database fiasco
  version per database file, keyed on the file modification time and
  size so that rebuilding the database invalidates the cache. This
  avoids re-reading the full ion index on every Ion instantiation.

Ion instantiation drops from ~3.7 ms to ~1.9 ms and
fiasco.proton_electron_ratio from ~2.1 s to ~1.5 s. O VI level
populations (21 T x 9 n): 9.3 -> 8.1 s, dominated by np.linalg.solve.
Rather than constructing an Element instance (and thus an Ion instance
for every ionization stage) of every element just to read the tabulated
ionization fraction data, read the ioneq data directly from the
database and instantiate only the first ion of each element to resolve
the abundance exactly as before. The iteration order, arithmetic,
warning messages, and missing-dataset behavior are unchanged such that
the result is bit-identical, including on databases with missing
ionization fraction datasets.

Also use the memoized atomic number/symbol lookups in list_elements,
list_ions, get_isoelectronic_sequence, and Element.

fiasco.proton_electron_ratio drops from ~1.4 s to ~0.4 s. O VI level
populations (21 T x 9 n): 8.1 -> 6.9 s. The full test suite also runs
roughly twice as fast.
@nabobalis nabobalis changed the title Speed 3 - Needs Speed 2 Fast X: level populations edition Aug 11, 2026
@nabobalis

Copy link
Copy Markdown
Collaborator Author

LOOK AT THE CI FLY. ALSO AS GOOD AS MY PIDGEOT WITH THE HM FLY

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