Skip to content

Add explicit fixed-mode projectors for native convergence #8

Add explicit fixed-mode projectors for native convergence

Add explicit fixed-mode projectors for native convergence #8

name: Cosmology Q-R2 resolution ladder
on:
push:
branches:
- dark-sector-stability-architecture
paths:
- 'dark_sector_architecture/qualification/fourier_resolution.py'
- 'dark_sector_architecture/qualification/run_qr2_resolution_pair.py'
- 'dark_sector_architecture/qualification/latfield_hdf5.py'
- 'dark_sector_architecture/qualification/weak_field_tensors.py'
- 'dark_sector_architecture/qualification/modal_convergence.py'
- '.github/workflows/cosmology-q-r2-resolution-pair.yml'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: cosmology-q-r2-resolution-ladder
cancel-in-progress: true
jobs:
q-r2-pair:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
GEVOLUTION_SHA: 0cca42e51a824002ae4fb602cbd79d671e8ffe60
LATFIELD2_SHA: 2d8c737ab6adc965a1d2718c209f5085af27b09c
TEMPLATE_BLOB: d4de9a5400ef58f6a0181fbe61f18056b233a425
SEED: 424242
BOXSIZE: 64.0
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
ref: dark-sector-stability-architecture
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install build and analysis 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: Fetch pinned gevolution and canonical CPU LATfield2
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"
printf 'gevolution=%s\nLATfield2=%s\n' \
"$(git -C gevolution rev-parse HEAD)" \
"$(git -C LATfield2 rev-parse HEAD)" \
| tee qr2_upstream_revisions.txt
- name: Fetch and verify canonical sc1 particle template
run: |
curl -L --fail --silent --show-error \
https://raw.githubusercontent.com/gevolution-code/gevolution-1.2/df8a930732aae1bafa32fd839ee70728bb10773a/sc1_crystal.dat \
-o gevolution/qr2_template.dat
test "$(git hash-object gevolution/qr2_template.dat)" = "$TEMPLATE_BLOB"
- name: Compile gevolution with velocity output
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 -DEXACT_OUTPUT_REDSHIFTS -DVELOCITY"
test -x gevolution
- name: Build matched N8 and N16 settings
run: |
python - <<'PY'
from pathlib import Path
base = Path(
"dark_sector_architecture/qualification/gevolution_modal_pilot.ini"
).read_text()
def settings(n, tiling, tag):
text = base
replacements = {
"template file = pilot_template.dat": "template file = qr2_template.dat",
"tiling factor = 2": f"tiling factor = {tiling}",
"Ngrid = 8": f"Ngrid = {n}",
"output path = ../pilot_output/": f"output path = ../qr2_{tag}_output/",
"generic file base = modalpilot": f"generic file base = qr2_{tag}",
"snapshot file base = modalpilot_snap": f"snapshot file base = qr2_{tag}_snap",
"Pk file base = modalpilot_pk": f"Pk file base = qr2_{tag}_pk",
}
for old, new in replacements.items():
if old not in text:
raise SystemExit(f"missing expected settings token: {old}")
text = text.replace(old, new, 1)
return text
Path("gevolution/qr2_n8.ini").write_text(settings(8, 2, "n8"))
Path("gevolution/qr2_n16.ini").write_text(settings(16, 4, "n16"))
Path("gevolution/qr2_n32.ini").write_text(settings(32, 8, "n32"))
PY
cat gevolution/qr2_n8.ini
cat gevolution/qr2_n16.ini
cat gevolution/qr2_n32.ini
- name: Run matched N8 development member
run: |
set -o pipefail
rm -rf qr2_n8_output
mkdir -p qr2_n8_output
cd gevolution
mpirun --oversubscribe -np 4 ./gevolution -n 2 -m 2 -s qr2_n8.ini \
| tee ../qr2_n8.log
- name: Run matched N16 development member
run: |
set -o pipefail
rm -rf qr2_n16_output
mkdir -p qr2_n16_output
cd gevolution
mpirun --oversubscribe -np 4 ./gevolution -n 2 -m 2 -s qr2_n16.ini \
| tee ../qr2_n16.log
- name: Run matched N32 development member
run: |
set -o pipefail
rm -rf qr2_n32_output
mkdir -p qr2_n32_output
cd gevolution
mpirun --oversubscribe -np 4 ./gevolution -n 2 -m 2 -s qr2_n32.ini \
| tee ../qr2_n32.log
- name: Verify matched output epochs and required fields
run: |
python - <<'PY'
import re
from pathlib import Path
pattern = re.compile(r"writing snapshot at z = ([0-9eE+.-]+)")
values = {}
for tag in ("n8", "n16", "n32"):
text = Path(f"qr2_{tag}.log").read_text()
match = pattern.search(text)
if match is None:
raise SystemExit(f"no snapshot redshift found for {tag}")
values[tag] = float(match.group(1))
for token in ("_phi.h5", "_v.h5"):
files = list(Path(f"qr2_{tag}_output").glob(f"*{token}"))
if not files:
raise SystemExit(f"missing {tag} {token}")
print("snapshot redshifts:", values)
if max(values.values()) - min(values.values()) > 1e-12:
raise SystemExit(f"output epochs do not match: {values}")
Path("qr2_output_epoch.txt").write_text(
f'{values["n8"]:.17g}\n'
)
PY
- name: Measure N8-N16 phase compatibility and resolution difference
run: |
low_phi="$(find qr2_n8_output -type f -name '*_phi.h5' | head -n 1)"
low_v="$(find qr2_n8_output -type f -name '*_v.h5' | head -n 1)"
high_phi="$(find qr2_n16_output -type f -name '*_phi.h5' | head -n 1)"
high_v="$(find qr2_n16_output -type f -name '*_v.h5' | head -n 1)"
python dark_sector_architecture/qualification/run_qr2_resolution_pair.py \
--low-phi "$low_phi" \
--low-velocity "$low_v" \
--high-phi "$high_phi" \
--high-velocity "$high_v" \
--boxsize "$BOXSIZE" \
--output dark_sector_architecture/qualification/results/q_r2_n8_n16_resolution_pair.json
- name: Measure N16-N32 phase compatibility and resolution difference
run: |
low_phi="$(find qr2_n16_output -type f -name '*_phi.h5' | head -n 1)"
low_v="$(find qr2_n16_output -type f -name '*_v.h5' | head -n 1)"
high_phi="$(find qr2_n32_output -type f -name '*_phi.h5' | head -n 1)"
high_v="$(find qr2_n32_output -type f -name '*_v.h5' | head -n 1)"
python dark_sector_architecture/qualification/run_qr2_resolution_pair.py \
--low-phi "$low_phi" \
--low-velocity "$low_v" \
--high-phi "$high_phi" \
--high-velocity "$high_v" \
--boxsize "$BOXSIZE" \
--output dark_sector_architecture/qualification/results/q_r2_n16_n32_resolution_pair.json
- name: Add run provenance
run: |
python - <<'PY'
import json
from pathlib import Path
epoch = float(Path("qr2_output_epoch.txt").read_text())
pairs = [
("q_r2_n8_n16_resolution_pair.json", 8, 16, 2, 4, 512, 4096),
("q_r2_n16_n32_resolution_pair.json", 16, 32, 4, 8, 4096, 32768),
]
root = Path("dark_sector_architecture/qualification/results")
for filename, low_n, high_n, low_tiling, high_tiling, low_p, high_p in pairs:
path = root / filename
data = json.loads(path.read_text())
data["pair_definition"] = {
"seed": 424242,
"template_source": "gevolution-code/gevolution-1.2/sc1_crystal.dat",
"template_blob": "d4de9a5400ef58f6a0181fbe61f18056b233a425",
"gevolution_sha": "0cca42e51a824002ae4fb602cbd79d671e8ffe60",
"latfield2_sha": "2d8c737ab6adc965a1d2718c209f5085af27b09c",
"low_grid": low_n,
"high_grid": high_n,
"low_tiling": low_tiling,
"high_tiling": high_tiling,
"low_particles": low_p,
"high_particles": high_p,
"requested_snapshot_redshift": 99.0,
"actual_snapshot_redshift": epoch,
}
path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n")
PY
- name: Upload paired-resolution artifact
uses: actions/upload-artifact@v4
with:
name: cosmology-q-r2-resolution-ladder
path: |
qr2_upstream_revisions.txt
gevolution/qr2_n8.ini
gevolution/qr2_n16.ini
gevolution/qr2_n32.ini
qr2_n8.log
qr2_n16.log
qr2_n32.log
qr2_output_epoch.txt
qr2_n8_output/*_phi.h5
qr2_n8_output/*_v.h5
qr2_n16_output/*_phi.h5
qr2_n16_output/*_v.h5
qr2_n32_output/*_phi.h5
qr2_n32_output/*_v.h5
dark_sector_architecture/qualification/results/q_r2_n8_n16_resolution_pair.json
dark_sector_architecture/qualification/results/q_r2_n16_n32_resolution_pair.json
if-no-files-found: error
- name: Persist paired-resolution report
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/q_r2_n8_n16_resolution_pair.json \
dark_sector_architecture/qualification/results/q_r2_n16_n32_resolution_pair.json
if git diff --cached --quiet; then
echo "Q-R2 report unchanged."
exit 0
fi
git commit -m "Persist Q-R2 resolution ladder"
git fetch origin dark-sector-stability-architecture
git rebase origin/dark-sector-stability-architecture
git push origin HEAD:dark-sector-stability-architecture