Add late-time material relational development workflow #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Cosmology late-time material relational development | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: | |
| - dark-sector-stability-architecture | |
| paths: | |
| - '.github/workflows/cosmology-late-time-material-relational-development.yml' | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: cosmology-late-time-material-relational-development | |
| cancel-in-progress: true | |
| jobs: | |
| development: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 75 | |
| env: | |
| GEVOLUTION_SHA: 0cca42e51a824002ae4fb602cbd79d671e8ffe60 | |
| LATFIELD2_SHA: 2d8c737ab6adc965a1d2718c209f5085af27b09c | |
| TEMPLATE_BLOB: d4de9a5400ef58f6a0181fbe61f18056b233a425 | |
| BOXSIZE: 64.0 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: dark-sector-stability-architecture | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential openmpi-bin libopenmpi-dev libfftw3-dev libgsl-dev libhdf5-dev | |
| python -m pip install --upgrade pip | |
| python -m pip install numpy h5py | |
| - name: Verify frozen APQ adjudication | |
| run: | | |
| git log -1 --format=%H -- dark_sector_architecture/LATE_TIME_MATERIAL_RELATIONAL_APQ2_ADJUDICATION_v0.1.md \ | |
| | tee material_relational_apq_commit.txt | |
| - name: Fetch pinned sources and template | |
| run: | | |
| git clone https://github.com/gevolution-code/gevolution-1.3.git gevolution | |
| git -C gevolution checkout "$GEVOLUTION_SHA" | |
| git clone https://gitlab.uzh.ch/julian.adamek/LATfield2.git LATfield2 | |
| git -C LATfield2 checkout "$LATFIELD2_SHA" | |
| curl -L --fail --silent --show-error \ | |
| https://raw.githubusercontent.com/gevolution-code/gevolution-1.2/df8a930732aae1bafa32fd839ee70728bb10773a/sc1_crystal.dat \ | |
| -o gevolution/material_relational_template.dat | |
| test "$(git hash-object gevolution/material_relational_template.dat)" = "$TEMPLATE_BLOB" | |
| - name: Patch dynamic hij output and full-precision snapshot metadata | |
| run: | | |
| python - <<'PY' | |
| from pathlib import Path | |
| path=Path('gevolution/main.cpp') | |
| text=path.read_text() | |
| marker=( | |
| '\t\t// snapshot output\n' | |
| '\t\tif (snapcount < sim.num_snapshot && ' | |
| '1. / a < sim.z_snapshot[snapcount] + 1.)\n' | |
| ) | |
| if marker not in text: | |
| raise SystemExit('snapshot marker missing') | |
| replacement=( | |
| '\t\t// snapshot output\n' | |
| '#ifdef TENSOR_EVOLUTION\n' | |
| '\t\tif ((sim.out_snapshot & MASK_HIJ) &&\n' | |
| '\t\t snapcount < sim.num_snapshot &&\n' | |
| '\t\t 1. / a < sim.z_snapshot[snapcount] + 1.)\n' | |
| '\t\t{\n' | |
| '\t\t\tplan_hij.execute(FFT_BACKWARD);\n' | |
| '\t\t\tSij.updateHalo();\n' | |
| '\t\t\tdone_hij = 1;\n' | |
| '\t\t}\n' | |
| '#endif\n' | |
| '\t\tif (snapcount < sim.num_snapshot && ' | |
| '1. / a < sim.z_snapshot[snapcount] + 1.)\n' | |
| '\t\t{\n' | |
| '\t\t\tchar material_meta[256];\n' | |
| '\t\t\tsprintf(material_meta, ' | |
| '"MATERIAL_REL_META index=%d cycle=%d a=%.17g z=%.17g ' | |
| 'tau_over_boxsize=%.17g", snapcount, cycle, a, (1./a)-1., tau);\n' | |
| '\t\t\tCOUT << material_meta << endl;\n' | |
| '\t\t}\n' | |
| '\t\tif (snapcount < sim.num_snapshot && ' | |
| '1. / a < sim.z_snapshot[snapcount] + 1.)\n' | |
| ) | |
| path.write_text(text.replace(marker,replacement,1)) | |
| PY | |
| - name: Compile gevolution | |
| working-directory: gevolution | |
| run: | | |
| make clean | |
| make -j2 \ | |
| INCLUDE="-I../LATfield2 -I/usr/include/hdf5/serial" \ | |
| LIB="-lfftw3 -lm -L/usr/lib/x86_64-linux-gnu/hdf5/serial -lhdf5 -lgsl -lgslcblas" \ | |
| DGEVOLUTION="-DPHINONLINEAR -DBENCHMARK -DVELOCITY -DTENSOR_EVOLUTION" | |
| - name: Build frozen N64 fifteen-snapshot settings | |
| run: | | |
| python - <<'PY' | |
| from pathlib import Path | |
| import json | |
| base=Path('dark_sector_architecture/qualification/gevolution_modal_pilot.ini').read_text() | |
| centers=[1/3,1/2,2/3] | |
| offsets=[0.995,0.9975,1.0,1.0025,1.005] | |
| scale_factors=[c*f for c in centers for f in offsets] | |
| if any(b <= a for a,b in zip(scale_factors,scale_factors[1:])): | |
| raise SystemExit('scale factors not globally increasing') | |
| redshifts=[1/a-1 for a in scale_factors] | |
| rtext=', '.join(f'{z:.12f}' for z in redshifts) | |
| replacements={ | |
| 'template file = pilot_template.dat':'template file = material_relational_template.dat', | |
| 'tiling factor = 2':'tiling factor = 16', | |
| 'Ngrid = 8':'Ngrid = 64', | |
| 'time step limit = 0.04':'time step limit = 0.0005', | |
| 'output path = ../pilot_output/':'output path = ../material_relational_output/', | |
| 'generic file base = modalpilot':'generic file base = material_relational', | |
| 'snapshot file base = modalpilot_snap':'snapshot file base = material_relational_snap', | |
| 'snapshot redshifts = 99':f'snapshot redshifts = {rtext}', | |
| 'snapshot outputs = phi, B, chi, hij, v':'snapshot outputs = phi, B, chi, hij, v, particles', | |
| 'Pk file base = modalpilot_pk':'Pk file base = material_relational_pk', | |
| 'Pk redshifts = 99':f'Pk redshifts = {redshifts[7]:.12f}', | |
| } | |
| text=base | |
| for old,new in replacements.items(): | |
| if old not in text: | |
| raise SystemExit(f'missing settings token: {old}') | |
| text=text.replace(old,new,1) | |
| Path('gevolution/material_relational.ini').write_text(text) | |
| Path('material_relational_requested.json').write_text( | |
| json.dumps({ | |
| 'grid':64,'seed':424242,'boxsize_mpc_over_h':64.0, | |
| 'scale_factors':scale_factors,'requested_redshifts':redshifts, | |
| 'central_indices':[2,7,12],'time_step_limit':0.0005 | |
| },indent=2,sort_keys=True)+'\n' | |
| ) | |
| PY | |
| - name: Run development trajectory | |
| run: | | |
| set -o pipefail | |
| rm -rf material_relational_output | |
| mkdir -p material_relational_output | |
| cd gevolution | |
| mpirun --oversubscribe -np 4 ./gevolution -n 2 -m 2 -s material_relational.ini \ | |
| | tee ../material_relational.log | |
| - name: Parse exact metadata and verify outputs | |
| run: | | |
| python - <<'PY' | |
| import json,re | |
| from pathlib import Path | |
| req=json.loads(Path('material_relational_requested.json').read_text()) | |
| text=Path('material_relational.log').read_text() | |
| pattern=re.compile( | |
| r'MATERIAL_REL_META index=([0-9]+) cycle=([0-9]+) ' | |
| r'a=([0-9eE+.-]+) z=([0-9eE+.-]+) tau_over_boxsize=([0-9eE+.-]+)' | |
| ) | |
| matches=pattern.findall(text) | |
| if len(matches)!=15: | |
| raise SystemExit(f'expected 15 snapshot metadata lines, got {len(matches)}') | |
| root=Path('material_relational_output') | |
| snaps=[] | |
| for j,(idx,cycle,a,z,tau) in enumerate(matches): | |
| if int(idx)!=j: | |
| raise SystemExit('snapshot index mismatch') | |
| for token in ('phi','chi','B','hij','v','cdm'): | |
| files=list(root.glob(f'*snap{j:03d}_{token}.h5')) | |
| if len(files)!=1: | |
| raise SystemExit(f'missing snap{j:03d}_{token}: {files}') | |
| snaps.append({ | |
| 'index':j, | |
| 'requested_redshift':req['requested_redshifts'][j], | |
| 'actual_scale_factor':float(a), | |
| 'actual_redshift':float(z), | |
| 'cycle':int(cycle), | |
| 'tau_over_boxsize':float(tau), | |
| }) | |
| taus=[x['tau_over_boxsize'] for x in snaps] | |
| if any(b<=a for a,b in zip(taus,taus[1:])): | |
| raise SystemExit('conformal times not strictly increasing') | |
| for center in req['central_indices']: | |
| cycles=[snaps[i]['cycle'] for i in range(center-2,center+3)] | |
| if len(set(cycles))!=5: | |
| raise SystemExit(f'central cluster {center} lacks distinct cycles: {cycles}') | |
| meta={ | |
| 'protocol':'P0-Q_LATE_TIME_MATERIAL_RELATIONAL_MEMBER', | |
| 'grid':64,'seed':424242,'boxsize_mpc_over_h':64.0, | |
| 'gevolution_sha':'0cca42e51a824002ae4fb602cbd79d671e8ffe60', | |
| 'latfield2_sha':'2d8c737ab6adc965a1d2718c209f5085af27b09c', | |
| 'snapshots':snaps, | |
| } | |
| out=Path('dark_sector_architecture/qualification/results') | |
| out.mkdir(parents=True,exist_ok=True) | |
| (out/'late_time_material_relational_metadata.json').write_text( | |
| json.dumps(meta,indent=2,sort_keys=True)+'\n' | |
| ) | |
| PY | |
| - name: Run frozen development analysis | |
| run: | | |
| python dark_sector_architecture/qualification/run_late_time_material_relational_development.py \ | |
| --snapshot-dir material_relational_output \ | |
| --metadata dark_sector_architecture/qualification/results/late_time_material_relational_metadata.json \ | |
| --output dark_sector_architecture/qualification/results/late_time_material_relational_development.json | |
| - name: Add frozen provenance | |
| run: | | |
| python - <<'PY' | |
| import json | |
| from pathlib import Path | |
| p=Path('dark_sector_architecture/qualification/results/late_time_material_relational_development.json') | |
| d=json.loads(p.read_text()) | |
| d['frozen_apq_adjudication_commit']=Path('material_relational_apq_commit.txt').read_text().strip() | |
| d['workflow_head']='${{ github.sha }}' | |
| p.write_text(json.dumps(d,indent=2,sort_keys=True)+'\n') | |
| print(json.dumps({ | |
| 'development_outcome':d['development_outcome'], | |
| 'delta_rel':d['primary_z2_to_z1']['delta_rel'], | |
| 'shift_q95':d['primary_z2_to_z1']['shift_null']['delta_rel_q95'], | |
| 'sse_persistence':d['primary_z2_to_z1']['sse_persistence'], | |
| 'sse_b0':d['primary_z2_to_z1']['sse_b0'], | |
| 'sse_b1':d['primary_z2_to_z1']['sse_b1'] | |
| },sort_keys=True)) | |
| PY | |
| - name: Upload compact development artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: cosmology-late-time-material-relational-development | |
| path: | | |
| material_relational_apq_commit.txt | |
| material_relational_requested.json | |
| material_relational.log | |
| gevolution/material_relational.ini | |
| dark_sector_architecture/qualification/results/late_time_material_relational_metadata.json | |
| dark_sector_architecture/qualification/results/late_time_material_relational_development.json | |
| if-no-files-found: error | |
| - name: Persist development summaries | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add \ | |
| dark_sector_architecture/qualification/results/late_time_material_relational_metadata.json \ | |
| dark_sector_architecture/qualification/results/late_time_material_relational_development.json | |
| if git diff --cached --quiet; then exit 0; fi | |
| git commit -m "Persist late-time material relational development" | |
| for attempt in 1 2 3 4 5; do | |
| git fetch origin dark-sector-stability-architecture | |
| git rebase origin/dark-sector-stability-architecture | |
| if git push origin HEAD:dark-sector-stability-architecture; then exit 0; fi | |
| sleep 2 | |
| done | |
| exit 1 |