RadCluster
Graph-based cluster dynamics for irradiated materials
Loading...
Searching...
No Matches
Functions | Variables
campaign_tally Namespace Reference

Functions

 load_by_machine (Path res_dir, str stem)
 
 load_starts (Path res_dir, str stem)
 
int _machine_from_name (str name, str stem)
 
 owned_counts (Path design, int of, weights)
 
 _warn_orphaned_output (Path res_dir, str stem, here_k)
 
 fmt_eta (hours)
 
 main (argv=None)
 

Variables

 HERE = Path(__file__).resolve().parent
 

Detailed Description

Tally a multi-machine campaign: who has reported what, and is it poolable.

Run this after `git pull` on any participating machine.  It answers the three
questions that matter between pulls:

  1. COVERAGE  - how many of the design's rows exist, per machine, against the
     count that machine OWNS under the frozen weights.  A machine that has not
     pushed is indistinguishable from a machine that has not started, so the
     table says "no file" rather than "0 done" for the former.

  2. POOLABILITY - whether every reported row carries the same git/solver/
     workbook/design/run_cfg hashes.  A split here means the rows cannot be
     pooled into one Sobol estimate, and it is silent unless something checks.
     This reuses merge_and_sobol.check_provenance so the two agree by
     construction.

  3. THROUGHPUT - completions per hour, computed from the rows themselves.
     NOT mean wall over completed rows: with W workers running concurrently,
     mean wall over the rows that HAVE finished is biased low early on, because
     the slow rows are precisely the ones still running.  Every ETA this
     campaign got wrong was got wrong that way.  Here, throughput is

         (rows done) / (elapsed wall on that machine)

     where elapsed comes from the machine's own first-to-last row span plus the
     wall of the longest row still in flight.  It converges from below and
     cannot flatter itself.

Usage:
    python campaign_status.py                      # frozen design in machines.json
    python campaign_status.py --design design/T3_rev6.csv
    python campaign_status.py --at-dose 0.1        # ladder view at one rung

Function Documentation

◆ _machine_from_name()

int campaign_tally._machine_from_name ( str  name,
str  stem 
)
protected

Definition at line 95 of file campaign_tally.py.

◆ _warn_orphaned_output()

campaign_tally._warn_orphaned_output ( Path  res_dir,
str  stem,
  here_k 
)
protected
Is a local worker appending to a file that no longer exists?

A held file handle names an inode, not a path.  Anything that replaces the
results file -- `git pull --rebase --autostash` above all, because a live
results file is always dirty -- leaves the worker writing to an unlinked
inode.  It is completely silent: the worker log keeps reporting completed
rows while the .jsonl stops growing, and the rows die with the process.
That cost 5 rows and 6.2 core-hours on 2026-08-06 before the log and the
file were compared by hand.

run_ensemble no longer holds the handle, so this cannot recur.  The check
stays because it also catches the same shape from any other cause (a
checkout, a stash pop, an editor writing through a temp file), and because
the failure gives no other symptom.

Definition at line 118 of file campaign_tally.py.

◆ fmt_eta()

campaign_tally.fmt_eta (   hours)

Definition at line 161 of file campaign_tally.py.

◆ load_by_machine()

campaign_tally.load_by_machine ( Path  res_dir,
str  stem 
)
{machine_index: {row_id: rec}}, plus the files each came from.

Keyed on the machine index recorded IN the row, not on the filename: a
file renamed or copied between hosts would otherwise be miscounted, and
the subtask suffix (_t3) already makes one machine write many files.

Definition at line 50 of file campaign_tally.py.

◆ load_starts()

campaign_tally.load_starts ( Path  res_dir,
str  stem 
)
{machine_index: marker} from the .started.json a live worker drops.

Definition at line 77 of file campaign_tally.py.

◆ main()

campaign_tally.main (   argv = None)

Definition at line 169 of file campaign_tally.py.

◆ owned_counts()

campaign_tally.owned_counts ( Path  design,
int  of,
  weights 
)
rows each machine index is responsible for, and the full row_id set.

Definition at line 106 of file campaign_tally.py.

Variable Documentation

◆ HERE

campaign_tally.HERE = Path(__file__).resolve().parent

Definition at line 44 of file campaign_tally.py.