Skip to content

Commit 403dd4f

Browse files
authored
Merge pull request #120 from underworldcode/feature/pixi-petsc-arch-static
Build cache coherence across PETSc version switches
2 parents f3debde + 15f8e1d commit 403dd4f

4 files changed

Lines changed: 105 additions & 43 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# activate-petsc-arch.sh — sourced by pixi on environment activation.
3+
#
4+
# Dynamically sets PETSC_ARCH for AMR environments (custom PETSc builds)
5+
# by combining the active pixi environment name with the PETSc version
6+
# pinned in petsc-custom/.petsc-version.
7+
#
8+
# This replaces hardcoded PETSC_ARCH entries in pixi.toml so that
9+
# switching PETSc versions (via ./uw petsc switch <tag>) does not require
10+
# editing tracked configuration.
11+
12+
_uw_mpi=""
13+
_uw_suffix=""
14+
15+
# Default MPI for AMR envs is platform-dependent and mirrors the conda deps
16+
# pinned in pixi.toml: openmpi on macOS (feature.amr.target.osx-arm64),
17+
# mpich on Linux (feature.amr.target.linux-64).
18+
_uw_default_mpi="mpich"
19+
[ "$(uname -s)" = "Darwin" ] && _uw_default_mpi="openmpi"
20+
21+
case "${PIXI_ENVIRONMENT_NAME:-}" in
22+
amr|amr-runtime|amr-dev) _uw_mpi="$_uw_default_mpi" ;;
23+
amr-mpich|amr-mpich-dev) _uw_mpi="mpich" ;;
24+
amr-openmpi|amr-openmpi-dev) _uw_mpi="openmpi" ;;
25+
amr-debug) _uw_mpi="$_uw_default_mpi"; _uw_suffix="-debug" ;;
26+
esac
27+
28+
if [ -n "$_uw_mpi" ]; then
29+
# Match the version-discovery logic in ./uw (petsc_version_short):
30+
# prefer .petsc-version, strip whitespace, fall back to 324.
31+
_uw_ver="324"
32+
_uw_ver_file="${PIXI_PROJECT_ROOT:-.}/petsc-custom/.petsc-version"
33+
if [ -f "$_uw_ver_file" ]; then
34+
_uw_read=$(tr -d '[:space:]' < "$_uw_ver_file" 2>/dev/null)
35+
[ -n "$_uw_read" ] && _uw_ver="$_uw_read"
36+
fi
37+
38+
export PETSC_ARCH="petsc-${_uw_ver}-uw-${_uw_mpi}${_uw_suffix}"
39+
fi
40+
41+
unset _uw_mpi _uw_suffix _uw_default_mpi _uw_ver _uw_ver_file _uw_read

pixi.toml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ cmake = ">=3.31,<4"
165165
make = ">=4.4,<5"
166166
mpi4py = ">=4,<5"
167167

168+
[feature.amr.activation]
169+
scripts = ["petsc-custom/activate-petsc-arch.sh"]
170+
168171
[feature.amr.activation.env]
169172
PETSC_DIR = "$PIXI_PROJECT_ROOT/petsc-custom/petsc"
170173

@@ -173,16 +176,10 @@ openmpi = ">=5.0,<6"
173176
hdf5 = { version = ">=1.14,<2", build = "*openmpi*" }
174177
h5py = { version = ">=3.12,<4", build = "*openmpi*" }
175178

176-
[feature.amr.target.osx-arm64.activation.env]
177-
PETSC_ARCH = "petsc-4-uw-openmpi"
178-
179179
[feature.amr.target.linux-64.dependencies]
180180
hdf5 = { version = ">=1.14,<2", build = "*mpich*" }
181181
h5py = { version = ">=3.12,<4", build = "*mpich*" }
182182

183-
[feature.amr.target.linux-64.activation.env]
184-
PETSC_ARCH = "petsc-4-uw-mpich"
185-
186183
[feature.amr.tasks]
187184
petsc-local-build = { cmd = "./build-petsc.sh", cwd = "petsc-custom" }
188185
petsc-local-clean = { cmd = "./build-petsc.sh clean", cwd = "petsc-custom" }
@@ -202,9 +199,11 @@ mpi4py = ">=4,<5"
202199
hdf5 = { version = ">=1.14,<2", build = "*mpich*" }
203200
h5py = { version = ">=3.12,<4", build = "*mpich*" }
204201

202+
[feature.amr-mpich.activation]
203+
scripts = ["petsc-custom/activate-petsc-arch.sh"]
204+
205205
[feature.amr-mpich.activation.env]
206206
PETSC_DIR = "$PIXI_PROJECT_ROOT/petsc-custom/petsc"
207-
PETSC_ARCH = "petsc-4-uw-mpich"
208207

209208
[feature.amr-mpich.tasks]
210209
petsc-local-build = { cmd = "./build-petsc.sh", cwd = "petsc-custom" }
@@ -221,9 +220,11 @@ mpi4py = ">=4,<5"
221220
hdf5 = { version = ">=1.14,<2", build = "*openmpi*" }
222221
h5py = { version = ">=3.12,<4", build = "*openmpi*" }
223222

223+
[feature.amr-openmpi.activation]
224+
scripts = ["petsc-custom/activate-petsc-arch.sh"]
225+
224226
[feature.amr-openmpi.activation.env]
225227
PETSC_DIR = "$PIXI_PROJECT_ROOT/petsc-custom/petsc"
226-
PETSC_ARCH = "petsc-4-uw-openmpi"
227228

228229
[feature.amr-openmpi.tasks]
229230
petsc-local-build = { cmd = "./build-petsc.sh", cwd = "petsc-custom" }
@@ -236,19 +237,26 @@ petsc-local-clean = { cmd = "./build-petsc.sh clean", cwd = "petsc-custom" }
236237
# Uses the same conda deps as amr but points to a separate PETSC_ARCH
237238
# so the optimised build is untouched.
238239
#
239-
# Setup:
240+
# PETSC_ARCH is set dynamically by petsc-custom/activate-petsc-arch.sh
241+
# and resolves to: petsc-<ver>-uw-<mpi>-debug
242+
# where <ver> comes from petsc-custom/.petsc-version and <mpi> follows
243+
# the platform default (openmpi on macOS, mpich on Linux).
244+
#
245+
# Setup (inside a pixi shell -e amr-debug, so $PETSC_ARCH is already set):
240246
# cd petsc-custom/petsc
241247
# pixi run -e amr-debug python3 ./configure \
242-
# --with-petsc-arch=petsc-4-uw-openmpi-debug --with-debugging=1 \
248+
# --with-petsc-arch="$PETSC_ARCH" --with-debugging=1 \
243249
# --with-mpi-dir="$CONDA_PREFIX" --with-hdf5=0 \
244250
# --download-mpich=0 --download-openmpi=0 --download-mpi4py=0 \
245251
# --with-petsc4py=0 --with-x=0 --with-pragmatic=0 --with-slepc=0 \
246252
# "--COPTFLAGS=-g -O0" "--CXXOPTFLAGS=-g -O0" "--FOPTFLAGS=-g -O0"
247-
# make PETSC_DIR=$(pwd) PETSC_ARCH=petsc-4-uw-openmpi-debug all
253+
# make PETSC_DIR=$(pwd) PETSC_ARCH="$PETSC_ARCH" all
254+
255+
[feature.amr-debug.activation]
256+
scripts = ["petsc-custom/activate-petsc-arch.sh"]
248257

249258
[feature.amr-debug.activation.env]
250259
PETSC_DIR = "$PIXI_PROJECT_ROOT/petsc-custom/petsc"
251-
PETSC_ARCH = "petsc-4-uw-openmpi-debug"
252260

253261
# ============================================
254262
# HPC CLUSTER FEATURE

setup.py

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -76,46 +76,42 @@ def configure():
7676
LIBRARY_DIRS = []
7777
LIBRARIES = []
7878

79-
PETSC_DIR = ""
80-
PETSC_ARCH = ""
81-
82-
# try get PETSC_DIR from petsc pip installation
83-
try:
84-
import petsc
85-
86-
PETSC_DIR = petsc.get_petsc_dir()
87-
except:
88-
pass
89-
90-
# PETSc
9179
import os
9280

93-
if not os.path.exists(PETSC_DIR):
94-
print(f"PETSC_INFO from petsc4py - {petsc4py.get_config()}")
95-
PETSC_DIR = petsc4py.get_config()["PETSC_DIR"]
96-
PETSC_ARCH = petsc4py.get_config()["PETSC_ARCH"]
97-
98-
# It is preferable to use the petsc4py paths to the
99-
# petsc libraries for consistency but the pip installation
100-
# of PETSc sometimes points to the temporary setup up path
101-
102-
if not os.path.exists(PETSC_DIR):
103-
print(f"PETSC_DIR {PETSC_DIR} is bad - trying another ...")
81+
PETSC_DIR = ""
82+
PETSC_ARCH = ""
10483

105-
if os.environ.get("CONDA_PREFIX") and not os.environ.get("PETSC_DIR"):
84+
# Priority 1: Environment variables (set by pixi activation for custom builds)
85+
if os.environ.get("PETSC_DIR") and os.path.exists(os.environ["PETSC_DIR"]):
86+
PETSC_DIR = os.environ["PETSC_DIR"]
87+
PETSC_ARCH = os.environ.get("PETSC_ARCH", "")
88+
89+
# Priority 2: petsc4py configuration (matches the installed petsc4py)
90+
if not PETSC_DIR or not os.path.exists(PETSC_DIR):
91+
config = petsc4py.get_config()
92+
PETSC_DIR = config["PETSC_DIR"]
93+
PETSC_ARCH = config.get("PETSC_ARCH", "")
94+
95+
# Priority 3: conda petsc package
96+
if not PETSC_DIR or not os.path.exists(PETSC_DIR):
97+
try:
98+
import petsc
99+
PETSC_DIR = petsc.get_petsc_dir()
100+
except ImportError:
101+
pass
102+
103+
# Priority 4: conda prefix fallback
104+
if not PETSC_DIR or not os.path.exists(PETSC_DIR):
105+
if os.environ.get("CONDA_PREFIX"):
106106
import sys
107-
108107
py_version = f"{sys.version_info.major}.{sys.version_info.minor}"
109108
PETSC_DIR = os.path.join(
110109
os.environ["CONDA_PREFIX"],
111110
"lib",
112111
"python" + py_version,
113112
"site-packages",
114113
"petsc",
115-
) # symlink to latest python
116-
PETSC_ARCH = os.environ.get("PETSC_ARCH", "")
117-
else:
118-
PETSC_DIR = os.environ["PETSC_DIR"]
114+
)
119115
PETSC_ARCH = os.environ.get("PETSC_ARCH", "")
120116

121117
print(f"Using PETSc:")

uw

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ run_build() {
159159
# Step 2: Check/build petsc4py
160160
if ! petsc4py_installed "$env"; then
161161
echo " Installing petsc4py for $env..."
162-
$PIXI run -e "$env" pip install "$PETSC_CUSTOM/src/binding/petsc4py" --no-build-isolation || {
162+
$PIXI run -e "$env" pip install "$PETSC_CUSTOM/src/binding/petsc4py" --no-build-isolation --no-cache-dir || {
163163
echo -e "${YELLOW}petsc4py build failed${NC}"
164164
exit 1
165165
}
@@ -293,8 +293,25 @@ run_petsc_cmd() {
293293
exit 1
294294
fi
295295
$PIXI run -e "$(get_env)" "$SCRIPT_DIR/petsc-custom/build-petsc.sh" checkout "$arg"
296+
297+
# Nuke stale build artifacts and petsc4py. The next ./uw build's
298+
# target-change detection can't fire because the still-installed
299+
# petsc4py reports the OLD arch, so we force a full rebuild here.
300+
# (run_build already passes --no-cache-dir to pip install . so we
301+
# don't need a global pip cache purge — only petsc4py's local-path
302+
# install needs its own --no-cache-dir.)
303+
echo ""
304+
echo "Clearing stale build artifacts for clean rebuild..."
305+
rm -rf "$SCRIPT_DIR"/build/lib.* "$SCRIPT_DIR"/build/temp.* "$SCRIPT_DIR"/build/bdist.* 2>/dev/null
306+
rm -f "$SCRIPT_DIR/build/.petsc_target"
307+
if is_amr_env "$(get_env)"; then
308+
echo "Uninstalling old petsc4py (linked to previous PETSc build)..."
309+
$PIXI run -e "$(get_env)" pip uninstall -y petsc4py 2>/dev/null || true
310+
fi
311+
296312
echo ""
297-
echo "To complete the switch, rebuild:"
313+
echo "To complete the switch, rebuild PETSc then underworld3:"
314+
echo " ./uw petsc build"
298315
echo " ./uw build"
299316
;;
300317
active)

0 commit comments

Comments
 (0)