#!/usr/bin/env bash
# ============================================================================
# build_grchombo_ax102.sh — GRChombo + Chombo + GRTresna on Hetzner AX102-1
# (AMD Ryzen 9 7950X3D 16C/32T, 128 GB DDR5 ECC, 2x1.92 TB NVMe, Ubuntu 24.04 LTS)
#
# usage: bash build_grchombo_ax102.sh [stage ...] (default: all)
# stages: pkgs clone config chombo grchombo grtresna env tests smoke python
# all = the ten stages above, in that order
# bench = MPI x OpenMP layout benchmark (only when named explicitly)
# tune = CPU governor -> performance (only when named explicitly)
#
# environment overrides:
# GRC_ROOT=$HOME/grchombo install root: sources, logs, smoke, bench, venv
# NJ=$(nproc) make parallelism
# GRCHOMBO_REF=main CHOMBO_REF=main GRTRESNA_REF=main branch / tag / commit
# WITH_AH=1 apparent-horizon finder (needs petsc-dev); PBH runs need it
# MARCH=native OPT=HIGH DEBUG=FALSE
# EXAMPLES="ScalarFieldCosmo" GRChombo examples to build
# TESTS="<all 3D tests>" GRChombo unit tests to build and run
# SMOKE_N=32 SMOKE_RANKS=4 smoke-test grid (N^3) and MPI ranks
# BENCH_N=96 BENCH_STEPS=10 BENCH_CONFIGS="16x1 8x2 4x4 32x1"
# PY_PKGS="numpy scipy matplotlib h5py yt"
#
# Verified 2026-09-29 (all stages, 17/17 tests, 3/3 smoke runs) on Ubuntu 24.04 on a
# Hetzner CCX33 (8 vCPU EPYC Milan, ~5 min) and a 2 vCPU VPS (~12 min) with GRChombo
# 37e6595 (main), Chombo fork 8684f2e (main), GRTresna 2e671e1 (main), GCC 13.3,
# OpenMPI 4.1.6, HDF5 1.10.10, PETSc 3.19.6. Sources of the recipe: GRChombo/.github/workflows/gcc-tests.yml and
# GRChombo/InstallNotes/MakeDefsLocalExamples/ubuntu-gcc.Make.defs.local.
# ============================================================================
set -Eeuo pipefail
GRC_ROOT=${GRC_ROOT:-$HOME/grchombo}
NJ=${NJ:-$(nproc)}
GRCHOMBO_REF=${GRCHOMBO_REF:-main}
CHOMBO_REF=${CHOMBO_REF:-main}
GRTRESNA_REF=${GRTRESNA_REF:-main}
WITH_AH=${WITH_AH:-1}
MARCH=${MARCH:-native}
OPT=${OPT:-HIGH}
DEBUG=${DEBUG:-FALSE}
EXAMPLES=${EXAMPLES:-ScalarFieldCosmo}
TESTS=${TESTS:-}
SMOKE_N=${SMOKE_N:-32}
SMOKE_RANKS=${SMOKE_RANKS:-4}
BENCH_N=${BENCH_N:-96}
BENCH_STEPS=${BENCH_STEPS:-10}
BENCH_CONFIGS=${BENCH_CONFIGS:-"16x1 8x2 4x4 32x1"}
PY_PKGS=${PY_PKGS:-"numpy scipy matplotlib h5py yt"}
CHOMBO_HOME=$GRC_ROOT/Chombo/lib
GRCHOMBO_HOME=$GRC_ROOT/GRChombo
GRTRESNA_HOME=$GRC_ROOT/GRTresna
LOG=$GRC_ROOT/logs
export CHOMBO_HOME
if [[ $(id -u) -eq 0 ]]; then
SUDO=""
export OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
else
SUDO="sudo"
fi
CUR_STAGE=start
err_report() { [[ -n ${ERR_REPORTED:-} ]] && return 0; ERR_REPORTED=1
echo "ERROR: build_grchombo_ax102.sh failed in stage \"$CUR_STAGE\" (line $1); logs in $LOG" >&2; }
trap 'err_report $LINENO' ERR
log() { printf '\n[%s] ===== %s =====\n' "$(date '+%F %T')" "$*"; }
die() { echo "ERROR: $*" >&2; exit 1; }
elapsed() { local s=$1; printf '%dm%02ds' $(( ($(date +%s) - s) / 60 )) $(( ($(date +%s) - s) % 60 )); }
# ---------------------------------------------------------------- pkgs
stage_pkgs() {
log "pkgs: apt packages"
. /etc/os-release
[[ ${VERSION_ID:-} == 24.04 ]] || echo "WARNING: recipe tested on Ubuntu 24.04; this is ${PRETTY_NAME:-unknown}"
local pkgs="build-essential gfortran csh perl make git pkg-config libgetopt-complete-perl
openmpi-bin libopenmpi-dev libhdf5-dev libhdf5-openmpi-dev hdf5-tools
libblas-dev liblapack-dev python3-venv python3-dev numactl hwloc tmux htop rsync bc"
(( WITH_AH )) && pkgs+=" petsc-dev"
$SUDO apt-get update -q
# shellcheck disable=SC2086
DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -q --no-install-recommends $pkgs
mpicxx --version | head -1
gfortran --version | head -1
}
# ---------------------------------------------------------------- clone
fetch_repo() { # url dir ref
local url=$1 dir=$2 ref=$3
if [[ -d $dir/.git ]]; then
git -C "$dir" fetch -q origin
else
git clone -q "$url" "$dir"
fi
if git -C "$dir" show-ref -q --verify "refs/remotes/origin/$ref"; then
git -C "$dir" checkout -q "$ref" 2>/dev/null || git -C "$dir" checkout -q -b "$ref" "origin/$ref"
git -C "$dir" merge -q --ff-only "origin/$ref" \
|| echo "WARNING: $dir has local commits on '$ref'; left as is (not fast-forwarded)"
else
git -C "$dir" checkout -q "$ref"
fi
printf '%-9s %s %s (%s)\n' "$(basename "$dir")" "$(git -C "$dir" rev-parse --short=12 HEAD)" \
"$(git -C "$dir" log -1 --format=%cs)" "$ref" | tee -a "$GRC_ROOT/VERSIONS.txt"
}
stage_clone() {
log "clone: Chombo (GRChombo fork), GRChombo, GRTresna -> $GRC_ROOT"
mkdir -p "$GRC_ROOT" "$LOG"
echo "# $(date -Is)" >> "$GRC_ROOT/VERSIONS.txt"
fetch_repo https://github.com/GRChombo/Chombo.git "$GRC_ROOT/Chombo" "$CHOMBO_REF"
fetch_repo https://github.com/GRChombo/GRChombo.git "$GRCHOMBO_HOME" "$GRCHOMBO_REF"
fetch_repo https://github.com/GRTLCollaboration/GRTresna.git "$GRTRESNA_HOME" "$GRTRESNA_REF"
}
# ---------------------------------------------------------------- config
stage_config() {
log "config: $CHOMBO_HOME/mk/Make.defs.local"
[[ -d $CHOMBO_HOME/mk ]] || die "Chombo not cloned (run the clone stage first)"
local hdf_mpi_inc hdf_mpi_lib hdf_ser_inc hdf_ser_lib petsc_cpp="" petsc_lib=""
# Ubuntu's hdf5-*.pc files carry the paths only in Cflags/Libs (no includedir variable)
pc_first() { pkg-config "$1" "$2" 2>/dev/null | tr ' ' '\n' | grep -m1 "^$3" | sed "s/^$3//"; }
hdf_mpi_inc=$(pc_first --cflags-only-I hdf5-openmpi -I); hdf_mpi_inc=${hdf_mpi_inc:-/usr/include/hdf5/openmpi}
hdf_mpi_lib=$(pc_first --libs-only-L hdf5-openmpi -L); hdf_mpi_lib=${hdf_mpi_lib:-/usr/lib/x86_64-linux-gnu/hdf5/openmpi}
hdf_ser_inc=$(pc_first --cflags-only-I hdf5-serial -I); hdf_ser_inc=${hdf_ser_inc:-/usr/include/hdf5/serial}
hdf_ser_lib=$(pc_first --libs-only-L hdf5-serial -L); hdf_ser_lib=${hdf_ser_lib:-/usr/lib/x86_64-linux-gnu/hdf5/serial}
[[ -f $hdf_mpi_inc/hdf5.h ]] || die "parallel HDF5 headers not found in $hdf_mpi_inc (apt: libhdf5-openmpi-dev)"
if (( WITH_AH )); then
pkg-config --exists petsc || die "PETSc not found by pkg-config (apt: petsc-dev) — or set WITH_AH=0"
petsc_cpp="-I$(pkg-config --variable=includedir petsc) -DUSE_AHFINDER"
petsc_lib="$(pkg-config --libs petsc) -Wl,-rpath,$(pkg-config --variable=libdir petsc)"
fi
local cpu; cpu=$(lscpu | sed -n 's/^Model name: *//p' | head -1)
cat > "$CHOMBO_HOME/mk/Make.defs.local" <<EOF
# Generated by build_grchombo_ax102.sh on $(date -Is), host $(hostname), CPU: $cpu
# Based on GRChombo/InstallNotes/MakeDefsLocalExamples/ubuntu-gcc.Make.defs.local
DIM = 3
DEBUG = $DEBUG
OPT = $OPT
PRECISION = DOUBLE
PROFILE = FALSE
CXX = g++
FC = gfortran
MPI = TRUE
OPENMPCC = TRUE
MPICXX = mpicxx
USE_64 = TRUE
USE_HDF = TRUE
HDFINCFLAGS = -I$hdf_ser_inc
HDFLIBFLAGS = -L$hdf_ser_lib -lhdf5 -lz
HDFMPIINCFLAGS = -I$hdf_mpi_inc
HDFMPILIBFLAGS = -L$hdf_mpi_lib -lhdf5 -lz
NAMESPACE = TRUE
USE_MT = FALSE
# Chombo's GNU compiler file adds -std=c++14 -fopenmp itself (cxxcomflags); only the
# optimisation flags are set here. On the 7950X3D (Zen 4) -march=native = znver4 with
# GCC >= 13, which selects the AVX-512 branch of GRChombo's simd layer.
cxxoptflags = -march=$MARCH -O3
foptflags = -march=$MARCH -O3
# apparent-horizon finder (PETSc); empty if WITH_AH=0. '+=' keeps flags that an example's
# GNUmakefile sets before including Make.example (GRTresna: cxxcppflags = -DUSE_CTTK).
cxxcppflags += $petsc_cpp
syslibflags += -lblas -llapack $petsc_lib
EOF
cat "$CHOMBO_HOME/mk/Make.defs.local"
}
# ---------------------------------------------------------------- chombo
stage_chombo() {
log "chombo: libraries BaseTools BoxTools AMRTools AMRElliptic AMRTimeDependent (-j$NJ)"
mkdir -p "$LOG"; local t0; t0=$(date +%s)
make -j"$NJ" -C "$CHOMBO_HOME" BaseTools BoxTools AMRTools AMRElliptic AMRTimeDependent 2>&1 | tee "$LOG/chombo.log"
# with NAMESPACE=TRUE the libraries are named lib<name>3d_ch.<config>.a
ls "$CHOMBO_HOME"/libamrtimedependent3d*.a "$CHOMBO_HOME"/libamrelliptic3d*.a >/dev/null \
|| die "Chombo libraries missing after build (see $LOG/chombo.log)"
echo "chombo libraries built in $(elapsed "$t0"):"; ls "$CHOMBO_HOME"/lib*3d*.a
}
# ---------------------------------------------------------------- grchombo
stage_grchombo() {
mkdir -p "$LOG"
local ex t0
for ex in $EXAMPLES; do
log "grchombo: Examples/$ex (-j$NJ)"; t0=$(date +%s)
[[ -d $GRCHOMBO_HOME/Examples/$ex ]] || die "no such example: $ex"
make -j"$NJ" -C "$GRCHOMBO_HOME/Examples/$ex" all 2>&1 | tee "$LOG/grchombo_$ex.log"
ls "$GRCHOMBO_HOME/Examples/$ex"/Main_*3d*.ex >/dev/null || die "executable missing for $ex"
echo "$ex built in $(elapsed "$t0"): $(ls "$GRCHOMBO_HOME/Examples/$ex"/Main_*3d*.ex)"
done
}
# ---------------------------------------------------------------- grtresna
stage_grtresna() {
log "grtresna: Examples/ScalarFieldCosmo (initial-data solver, -j$NJ)"
mkdir -p "$LOG"; local t0; t0=$(date +%s)
make -j"$NJ" -C "$GRTRESNA_HOME/Examples/ScalarFieldCosmo" all 2>&1 | tee "$LOG/grtresna.log"
ls "$GRTRESNA_HOME/Examples/ScalarFieldCosmo"/Main_*3d*.ex >/dev/null || die "GRTresna executable missing"
echo "GRTresna built in $(elapsed "$t0"): $(ls "$GRTRESNA_HOME/Examples/ScalarFieldCosmo"/Main_*3d*.ex)"
}
# ---------------------------------------------------------------- env
stage_env() {
log "env: $GRC_ROOT/env.sh and $GRC_ROOT/bin/grcrun"
mkdir -p "$GRC_ROOT/bin"
{
echo "# source this file: . $GRC_ROOT/env.sh"
echo "export GRC_ROOT=$GRC_ROOT"
cat <<'EOF'
export CHOMBO_HOME=$GRC_ROOT/Chombo/lib
export GRCHOMBO_HOME=$GRC_ROOT/GRChombo
export GRTRESNA_HOME=$GRC_ROOT/GRTresna
export PATH=$GRC_ROOT/bin:$PATH
export OMP_NUM_THREADS=${OMP_NUM_THREADS:-1}
export OMP_PROC_BIND=true OMP_PLACES=cores
ulimit -s unlimited 2>/dev/null || true
if [ "$(id -u)" = 0 ]; then export OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1; fi
[ -f "$GRC_ROOT/venv/bin/activate" ] && . "$GRC_ROOT/venv/bin/activate"
EOF
} > "$GRC_ROOT/env.sh"
cat > "$GRC_ROOT/bin/grcrun" <<'EOF'
#!/usr/bin/env bash
# grcrun — run a GRChombo / GRTresna executable on one node: RANKS MPI ranks x THREADS OpenMP threads
# usage: grcrun [-n RANKS] [-t THREADS] [-o LOGFILE] [-v] EXE PARAMS [extra mpirun args ...]
# defaults: RANKS=16 THREADS=1 (all physical cores of the AX102-1, one rank per core).
# If RANKS*THREADS exceeds the physical cores, SMT hardware threads are used (e.g. -n 32).
set -Eeuo pipefail
R=${GRC_RANKS:-16}; T=${GRC_THREADS:-1}; LOGF=""; VERB=""
while getopts "n:t:o:v" o; do
case $o in n) R=$OPTARG;; t) T=$OPTARG;; o) LOGF=$OPTARG;; v) VERB="--report-bindings";; *) exit 2;; esac
done
shift $((OPTIND-1))
[[ $# -ge 2 ]] || { echo "usage: grcrun [-n RANKS] [-t THREADS] [-o LOG] [-v] EXE PARAMS [mpirun args]" >&2; exit 2; }
EXE=$(readlink -f "$1"); PAR=$2; shift 2
NPHYS=$(lscpu -p=core 2>/dev/null | grep -v '^#' | sort -u | wc -l); NPHYS=${NPHYS:-$(nproc)}
extra=()
if (( R * T > NPHYS )); then # SMT threads as processing elements
extra+=(--use-hwthread-cpus)
if (( T == 1 )); then extra+=(--map-by hwthread --bind-to hwthread)
else extra+=(--map-by "slot:PE=$T" --bind-to hwthread); fi
elif (( T == 1 )); then
extra+=(--map-by core --bind-to core)
else
extra+=(--map-by "slot:PE=$T" --bind-to core)
fi
[[ $(id -u) -eq 0 ]] && extra+=(--allow-run-as-root)
[[ -n $VERB ]] && extra+=("$VERB")
export OMP_NUM_THREADS=$T OMP_PROC_BIND=true OMP_PLACES=cores
cmd=(mpirun -n "$R" "${extra[@]}" -x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES "$@" "$EXE" "$PAR")
echo "[grcrun] $(date '+%F %T') ranks=$R threads=$T cwd=$PWD"
echo "[grcrun] ${cmd[*]}"
if [[ -n $LOGF ]]; then "${cmd[@]}" 2>&1 | tee "$LOGF"; else "${cmd[@]}"; fi
EOF
chmod +x "$GRC_ROOT/bin/grcrun"
echo "written: $GRC_ROOT/env.sh, $GRC_ROOT/bin/grcrun"
}
# ---------------------------------------------------------------- tests
stage_tests() {
local tests=$TESTS t rc pass=0 fail=0 failed=""
if [[ -z $tests ]]; then # all 3D tests (the 2D AH test needs a DIM=2 build)
tests=$(cd "$GRCHOMBO_HOME/Tests" && ls -d */ | tr -d / | grep -v 2D | tr '\n' ' ')
fi
log "tests: $tests"
mkdir -p "$LOG"
for t in $tests; do
printf '%-32s build ... ' "$t"
if make -j"$NJ" -C "$GRCHOMBO_HOME/Tests/$t" all >"$LOG/test_$t.build.log" 2>&1; then
printf 'run ... '
if make -C "$GRCHOMBO_HOME/Tests/$t" run >"$LOG/test_$t.run.log" 2>&1; then
echo PASS; pass=$((pass+1))
else
echo "FAIL (see $LOG/test_$t.run.log)"; fail=$((fail+1)); failed+=" $t"
fi
else
echo "BUILD FAILED (see $LOG/test_$t.build.log)"; fail=$((fail+1)); failed+=" $t"
fi
done
echo "tests: $pass passed, $fail failed${failed:+ ($failed)}"
(( fail == 0 )) || die "some GRChombo tests failed"
}
# ---------------------------------------------------------------- smoke
smoke_params_grchombo() { # src dst N box -> writes dst (short run: 8 steps, plot every 4)
local src=$1 dst=$2 n=$3 box=$4
sed -e "s/^N_full *=.*/N_full = $n/" \
-e "s/^max_box_size *=.*/max_box_size = $box/" \
-e "s/^min_box_size *=.*/min_box_size = $box/" \
-e "s/^checkpoint_interval *=.*/checkpoint_interval = 8/" \
-e "s/^plot_interval *=.*/plot_interval = 4/" \
-e "s/^verbosity *=.*/verbosity = 1/" "$src" > "$dst"
echo "max_steps = 8" >> "$dst"
}
stage_smoke() {
[[ -x $GRC_ROOT/bin/grcrun ]] || stage_env
local n=$SMOKE_N box=$(( SMOKE_N >= 32 ? 16 : 8 )) run=$GRC_ROOT/bin/grcrun t0
local exe texe d
exe=$(ls "$GRCHOMBO_HOME/Examples/ScalarFieldCosmo"/Main_ScalarFieldCosmo3d*.ex | head -1)
texe=$(ls "$GRTRESNA_HOME/Examples/ScalarFieldCosmo"/Main_ScalarFieldCosmo3d*.ex | head -1)
rm -rf "$GRC_ROOT/smoke"; mkdir -p "$GRC_ROOT/smoke"
log "smoke 1/3: GRChombo ScalarFieldCosmo, analytic initial data, N=$n, $SMOKE_RANKS ranks, 8 steps"
d=$GRC_ROOT/smoke/cosmo_analytic; mkdir -p "$d"; t0=$(date +%s)
smoke_params_grchombo "$GRCHOMBO_HOME/Examples/ScalarFieldCosmo/params.txt" "$d/params.txt" "$n" "$box"
(cd "$d" && "$run" -n "$SMOKE_RANKS" -t 1 -o run.log "$exe" params.txt >/dev/null)
[[ -f $d/hdf5/Cosmop_000008.3d.hdf5 ]] || die "smoke 1: plot file not written (see $d/run.log)"
grep -qi nan "$d/pout/pout.0" && die "smoke 1: NaN in pout"
echo "smoke 1 OK in $(elapsed "$t0"): $(ls "$d/hdf5" | tr '\n' ' ')"
# the GRTresna example is set up for N=64, L=128 (dx = 2); keep dx = 2 at any N (dx = 4 gives NaNs at step 1)
local L=$(( 2 * n ))
log "smoke 2/3: GRTresna constraint solver (CTTK), N=$n, L=$L, $SMOKE_RANKS ranks"
d=$GRC_ROOT/smoke/cosmo_grtresna; mkdir -p "$d"; t0=$(date +%s)
sed -e "s/^N *=.*/N = $n $n $n/" -e "s/^L *=.*/L = $L/" \
-e "s/^block_factor *=.*/block_factor = $box/" \
-e "s/^max_grid_size *=.*/max_grid_size = $box/" \
-e "s#^output_path *=.*#output_path = $d/solver_out/#" \
"$GRTRESNA_HOME/Examples/ScalarFieldCosmo/params.txt" > "$d/params_solver.txt"
(cd "$d" && "$run" -n "$SMOKE_RANKS" -t 1 -o solver.log "$texe" params_solver.txt >/dev/null)
[[ -f $d/solver_out/InitialDataFinal.3d.hdf5 ]] || die "smoke 2: solver output missing (see $d/solver.log)"
echo "smoke 2 OK in $(elapsed "$t0"): $(ls "$d/solver_out")"
log "smoke 3/3: GRChombo restart from the GRTresna data, 8 steps"
t0=$(date +%s)
smoke_params_grchombo "$GRCHOMBO_HOME/Examples/ScalarFieldCosmo/GRTresna_restart_setup/params_LR.txt" \
"$d/params_evolve.txt" "$n" "$box"
sed -i -e "s#^restart_file *=.*#restart_file = $d/solver_out/InitialDataFinal.3d.hdf5#" \
-e "s/^L_full *=.*/L_full = $L/" "$d/params_evolve.txt"
# on the restart code path GRChombo does not create the hdf5/pout/data sub-directories itself
mkdir -p "$d/hdf5_LR" "$d/pout_LR" "$d/data_LR"
(cd "$d" && "$run" -n "$SMOKE_RANKS" -t 1 -o evolve.log "$exe" params_evolve.txt >/dev/null)
[[ -f $d/hdf5_LR/Cosmop_000008.3d.hdf5 ]] || die "smoke 3: plot file not written (see $d/evolve.log)"
grep -qi nan "$d/pout_LR/pout.0" && die "smoke 3: NaN in pout"
echo "smoke 3 OK in $(elapsed "$t0"): $(ls "$d/hdf5_LR" | tr '\n' ' ')"
echo "smoke: all three runs passed"
}
# ---------------------------------------------------------------- bench
stage_bench() {
[[ -x $GRC_ROOT/bin/grcrun ]] || stage_env
local exe cfg r t d t0 dt run=$GRC_ROOT/bin/grcrun
exe=$(ls "$GRCHOMBO_HOME/Examples/ScalarFieldCosmo"/Main_ScalarFieldCosmo3d*.ex | head -1)
log "bench: ScalarFieldCosmo N=$BENCH_N, $BENCH_STEPS steps, configs: $BENCH_CONFIGS"
mkdir -p "$GRC_ROOT/bench"
{ echo "# $(date -Is) N=$BENCH_N steps=$BENCH_STEPS $(lscpu | sed -n 's/^Model name: *//p')"; echo "# ranks x threads wall[s]"; } > "$GRC_ROOT/bench/summary.txt"
for cfg in $BENCH_CONFIGS; do
r=${cfg%x*}; t=${cfg#*x}; d=$GRC_ROOT/bench/$cfg; rm -rf "$d"; mkdir -p "$d"
sed -e "s/^N_full *=.*/N_full = $BENCH_N/" -e "s/^checkpoint_interval *=.*/checkpoint_interval = 1000000/" \
-e "s/^plot_interval *=.*/plot_interval = -1/" \
"$GRCHOMBO_HOME/Examples/ScalarFieldCosmo/params.txt" > "$d/params.txt"
echo "max_steps = $BENCH_STEPS" >> "$d/params.txt"
t0=$(date +%s.%N)
(cd "$d" && "$run" -n "$r" -t "$t" -o run.log "$exe" params.txt >/dev/null) || { echo "$cfg FAILED"; continue; }
dt=$(echo "$(date +%s.%N) - $t0" | bc)
printf '%-8s %8.1f\n' "$cfg" "$dt" | tee -a "$GRC_ROOT/bench/summary.txt"
done
echo "bench summary: $GRC_ROOT/bench/summary.txt"
}
# ---------------------------------------------------------------- python
stage_python() {
log "python: venv $GRC_ROOT/venv ($PY_PKGS)"
[[ -d $GRC_ROOT/venv ]] || python3 -m venv "$GRC_ROOT/venv"
"$GRC_ROOT/venv/bin/pip" install -q -U pip
# shellcheck disable=SC2086
"$GRC_ROOT/venv/bin/pip" install -q $PY_PKGS
"$GRC_ROOT/venv/bin/python" -c "import h5py, numpy; print('h5py', h5py.__version__, 'numpy', numpy.__version__)"
}
# ---------------------------------------------------------------- tune (optional)
stage_tune() {
log "tune: CPU frequency governor -> performance"
DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -q --no-install-recommends linux-tools-common "linux-tools-$(uname -r)" || true
$SUDO cpupower frequency-set -g performance || echo "cpupower failed (amd-pstate in passive mode?) — not critical"
grep -h . /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || true
}
# ---------------------------------------------------------------- main
main() {
local stages=("$@") s T0
(( ${#stages[@]} )) || stages=(all)
[[ ${stages[*]} == *all* ]] && stages=(pkgs clone config chombo grchombo grtresna env tests smoke python)
T0=$(date +%s)
echo "build_grchombo_ax102.sh: GRC_ROOT=$GRC_ROOT NJ=$NJ WITH_AH=$WITH_AH MARCH=$MARCH OPT=$OPT DEBUG=$DEBUG"
echo "stages: ${stages[*]}"
for s in "${stages[@]}"; do
case $s in
pkgs|clone|config|chombo|grchombo|grtresna|env|tests|smoke|bench|python|tune) CUR_STAGE=$s; "stage_$s" ;;
*) die "unknown stage '$s'" ;;
esac
done
log "done in $(elapsed "$T0")"
[[ -f $GRC_ROOT/VERSIONS.txt ]] && { echo "versions:"; tail -3 "$GRC_ROOT/VERSIONS.txt"; }
echo "next: . $GRC_ROOT/env.sh ; grcrun -n 16 -t 1 <Main_*.ex> params.txt"
}
main "$@"