set shell := ["bash", "-euo", "pipefail", "-c"] meson_bin := env_var_or_default("MESON_BIN", "meson") python_bin := env_var_or_default("PYTHON", "python3") jobs := env_var_or_default("MFEM_JOBS", "4") allow_preinstalled := env_var_or_default("MFEM_ALLOW_PREINSTALLED", "false") dependency_prefix := env_var_or_default("MFEM_DEPENDENCY_PREFIX", "") cuda_home := env_var_or_default("CUDA_HOME", "") cuda_arch := env_var_or_default("MFEM_CUDA_ARCH", "native") web_port := env_var_or_default("MFEM_WEB_PORT", "8000") macos_target := env_var_or_default("MACOSX_DEPLOYMENT_TARGET", "11.0") project_root := justfile_directory() build_root := project_root + "/" + env_var_or_default("MFEM_BUILD_ROOT", "build") install_root := project_root + "/" + env_var_or_default("MFEM_INSTALL_ROOT", "install") basic_dir := build_root + "/basic" serial_dir := build_root + "/serial" parallel_dir := build_root + "/parallel" debug_dir := build_root + "/debug" cuda_dir := build_root + "/cuda" hip_dir := build_root + "/hip" wasm_dir := build_root + "/emscripten" wasm_cache := build_root + "/emscripten-cache" basic_install := install_root + "/basic" serial_install := install_root + "/serial" parallel_install := install_root + "/parallel" debug_install := install_root + "/debug" cuda_install := install_root + "/cuda" hip_install := install_root + "/hip" benchmark_trials := env_var_or_default("MFEM_BENCH_TRIALS", "5") benchmark_mesh_n := env_var_or_default("MFEM_BENCH_MESH_N", "48") benchmark_order := env_var_or_default("MFEM_BENCH_ORDER", "3") benchmark_applications := env_var_or_default("MFEM_BENCH_APPLICATIONS", "50") benchmark_minimum_apply_seconds := env_var_or_default("MFEM_BENCH_MIN_SECONDS", "1.0") benchmark_max_applications := env_var_or_default("MFEM_BENCH_MAX_APPLICATIONS", "1000000") benchmark_omp_threads := env_var_or_default("MFEM_BENCH_OMP_THREADS", "8") benchmark_mpi_ranks := env_var_or_default("MFEM_BENCH_MPI_RANKS", "4") cuda_cc := env_var_or_default("MFEM_CUDA_CC", env_var_or_default("CC", "cc")) cuda_cxx := env_var_or_default("MFEM_CUDA_CXX", env_var_or_default("CXX", "c++")) default: @just --list [private] configure dir install_dir buildtype profile allow *extra: #!/usr/bin/env bash set -euo pipefail setup_args=( "{{ dir }}" "--prefix={{ install_dir }}" "--buildtype={{ buildtype }}" "-Dfeature_profile={{ profile }}" "-Dallow_preinstalled={{ allow }}" "-Ddependency_prefix={{ dependency_prefix }}" "-Djobs={{ jobs }}" "-Dbuild_examples=true" "-Dbuild_tests=true" ) if [[ -f "{{ dir }}/meson-private/coredata.dat" ]]; then setup_args=(--reconfigure "${setup_args[@]}") fi "{{ meson_bin }}" setup "${setup_args[@]}" {{ extra }} [private] build-and-test dir: "{{ meson_bin }}" compile -C "{{ dir }}" "{{ meson_bin }}" test -C "{{ dir }}" --print-errorlogs basic: (configure basic_dir basic_install "release" "minimal" allow_preinstalled "-Dmfem_mpi=disabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled") (build-and-test basic_dir) serial: (configure serial_dir serial_install "release" "portable" allow_preinstalled "-Dmfem_mpi=disabled" "-Dmfem_metis=disabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled") (build-and-test serial_dir) parallel: (configure parallel_dir parallel_install "release" "portable" allow_preinstalled "-Dmfem_mpi=enabled" "-Dmfem_sundials=enabled" "-Dmfem_cuda=disabled" "-Dmfem_hip=disabled" "-Dbuild_benchmarks=true") (build-and-test parallel_dir) debug: (configure debug_dir debug_install "debug" "portable" allow_preinstalled) (build-and-test debug_dir) cuda: #!/usr/bin/env bash set -euo pipefail cuda_root="{{ cuda_home }}" if [[ -z "$cuda_root" ]]; then if command -v nvcc >/dev/null 2>&1; then nvcc_path="$(command -v nvcc)" while [[ -L "$nvcc_path" ]]; do nvcc_target="$(readlink "$nvcc_path")" if [[ "$nvcc_target" == /* ]]; then nvcc_path="$nvcc_target" else nvcc_path="$(dirname "$nvcc_path")/$nvcc_target" fi done cuda_root="$(cd "$(dirname "$nvcc_path")/.." && pwd -P)" elif [[ -x /usr/local/cuda/bin/nvcc ]]; then cuda_root=/usr/local/cuda fi fi if [[ -n "$cuda_root" ]]; then export CUDA_HOME="$cuda_root" export PATH="$cuda_root/bin:$PATH" fi if ! command -v nvcc >/dev/null 2>&1; then echo "CUDA was requested, but nvcc was not found; set CUDA_HOME or PATH." >&2 exit 2 fi selected_arch="{{ cuda_arch }}" if [[ "$selected_arch" == native ]] && command -v nvidia-smi >/dev/null 2>&1; then if detected_arch="$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader | sed -n '1{s/[[:space:].]//g;p;}')" && [[ "$detected_arch" =~ ^[0-9]+$ ]]; then selected_arch="$detected_arch" fi fi setup_args=( "{{ cuda_dir }}" "--prefix={{ cuda_install }}" "--buildtype=release" "-Dfeature_profile=portable" "-Dallow_preinstalled={{ allow_preinstalled }}" "-Ddependency_prefix={{ dependency_prefix }}" "-Djobs={{ jobs }}" "-Dbuild_examples=true" "-Dbuild_benchmarks=true" "-Dbuild_tests=true" "-Dmfem_cuda=enabled" "-Dmfem_hip=disabled" "-Dmfem_cuda_arch=${selected_arch}" ) if [[ -f "{{ cuda_dir }}/meson-private/coredata.dat" ]]; then setup_args=(--reconfigure "${setup_args[@]}") fi CC="{{ cuda_cc }}" CXX="{{ cuda_cxx }}" "{{ meson_bin }}" setup "${setup_args[@]}" "{{ meson_bin }}" compile -C "{{ cuda_dir }}" "{{ meson_bin }}" test -C "{{ cuda_dir }}" --print-errorlogs hip: (configure hip_dir hip_install "release" "portable" allow_preinstalled "-Dmfem_hip=enabled" "-Dmfem_cuda=disabled") (build-and-test hip_dir) emscripten: #!/usr/bin/env bash set -euo pipefail mkdir -p "{{ wasm_cache }}" setup_args=( "{{ wasm_dir }}" "--cross-file={{ project_root }}/cross/wasm32.ini" "--prefix={{ install_root }}/emscripten" "--buildtype=release" "-Dfeature_profile=portable" "-Dallow_preinstalled=false" "-Djobs={{ jobs }}" "-Dbuild_python=false" "-Dbuild_examples=true" "-Dbuild_tests=true" ) if [[ -f "{{ wasm_dir }}/meson-private/coredata.dat" ]]; then setup_args=(--reconfigure "${setup_args[@]}") fi EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" setup "${setup_args[@]}" EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" compile -C "{{ wasm_dir }}" EM_CACHE="{{ wasm_cache }}" "{{ meson_bin }}" test -C "{{ wasm_dir }}" --print-errorlogs serve-emscripten port=web_port: emscripten @echo "MFEM browser demo: http://0.0.0.0:{{ port }}" "{{ python_bin }}" -m http.server "{{ port }}" --bind 0.0.0.0 --directory "{{ wasm_dir }}/web" python: mkdir -p "{{ project_root }}/dist" MACOSX_DEPLOYMENT_TARGET="{{ macos_target }}" "{{ python_bin }}" -m build --wheel --no-isolation --outdir "{{ project_root }}/dist" run-serial: serial "{{ serial_dir }}/examples/mfem-serial-poisson" run-parallel ranks="4": parallel "{{ python_bin }}" "{{ project_root }}/tools/run_mpi_test.py" --launcher "{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" --processes "{{ ranks }}" "{{ parallel_dir }}/examples/mfem-parallel-hypre" run-cuda ranks="2": cuda "{{ python_bin }}" "{{ project_root }}/tools/run_mpi_test.py" --launcher "{{ cuda_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" --processes "{{ ranks }}" "{{ cuda_dir }}/examples/mfem-parallel-hypre" cuda benchmark: benchmark-cpu benchmark-cpu: parallel #!/usr/bin/env bash set -euo pipefail launcher="{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" dep_prefix="{{ dependency_prefix }}" if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do [[ -x "$candidate" ]] && launcher="$candidate" && break done fi if [[ ! -x "$launcher" ]]; then launcher="$(command -v mpiexec || command -v mpirun || true)" fi [[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; } if [[ -n "$dep_prefix" ]]; then export PATH="$dep_prefix/bin:$PATH" if [[ "$(uname -s)" == Darwin ]]; then export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}" else export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}" fi fi "{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \ --executable "{{ parallel_dir }}/benchmarks/mfem-backend-benchmark" \ --launcher "$launcher" \ --cases cpu,ceed-cpu,omp,mpi \ --omp-threads "{{ benchmark_omp_threads }}" \ --mpi-ranks "{{ benchmark_mpi_ranks }}" \ --trials "{{ benchmark_trials }}" \ --mesh-n "{{ benchmark_mesh_n }}" \ --order "{{ benchmark_order }}" \ --applications "{{ benchmark_applications }}" \ --minimum-apply-seconds "{{ benchmark_minimum_apply_seconds }}" \ --max-applications "{{ benchmark_max_applications }}" \ --output-dir "{{ parallel_dir }}/benchmarks/results" benchmark-cuda: cuda #!/usr/bin/env bash set -euo pipefail launcher="{{ cuda_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" dep_prefix="{{ dependency_prefix }}" if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do [[ -x "$candidate" ]] && launcher="$candidate" && break done fi if [[ ! -x "$launcher" ]]; then launcher="$(command -v mpiexec || command -v mpirun || true)" fi [[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; } if [[ -n "$dep_prefix" ]]; then export PATH="$dep_prefix/bin:$PATH" if [[ "$(uname -s)" == Darwin ]]; then export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}" else export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}" fi fi "{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \ --executable "{{ cuda_dir }}/benchmarks/mfem-backend-benchmark" \ --launcher "$launcher" \ --cases cpu,ceed-cpu,omp,mpi,cuda,ceed-cuda \ --omp-threads "{{ benchmark_omp_threads }}" \ --mpi-ranks "{{ benchmark_mpi_ranks }}" \ --trials "{{ benchmark_trials }}" \ --mesh-n "{{ benchmark_mesh_n }}" \ --order "{{ benchmark_order }}" \ --applications "{{ benchmark_applications }}" \ --minimum-apply-seconds "{{ benchmark_minimum_apply_seconds }}" \ --max-applications "{{ benchmark_max_applications }}" \ --output-dir "{{ cuda_dir }}/benchmarks/results" benchmark-quick: parallel #!/usr/bin/env bash set -euo pipefail launcher="{{ parallel_dir }}/build-config/mfem/mfem-prefix/bin/mpiexec" dep_prefix="{{ dependency_prefix }}" if [[ ! -x "$launcher" && -n "$dep_prefix" ]]; then for candidate in "$dep_prefix/bin/mpiexec" "$dep_prefix/bin/mpirun"; do [[ -x "$candidate" ]] && launcher="$candidate" && break done fi if [[ ! -x "$launcher" ]]; then launcher="$(command -v mpiexec || command -v mpirun || true)" fi [[ -n "$launcher" ]] || { echo "No MPI launcher was found." >&2; exit 2; } if [[ -n "$dep_prefix" ]]; then export PATH="$dep_prefix/bin:$PATH" if [[ "$(uname -s)" == Darwin ]]; then export DYLD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${DYLD_LIBRARY_PATH:-}" else export LD_LIBRARY_PATH="$dep_prefix/lib:$dep_prefix/lib64:${LD_LIBRARY_PATH:-}" fi fi "{{ python_bin }}" "{{ project_root }}/tools/run_backend_benchmarks.py" \ --executable "{{ parallel_dir }}/benchmarks/mfem-backend-benchmark" \ --launcher "$launcher" \ --cases cpu,ceed-cpu,omp,mpi \ --omp-threads "{{ benchmark_omp_threads }}" \ --mpi-ranks "{{ benchmark_mpi_ranks }}" \ --trials 1 --mesh-n 16 --order 2 --applications 5 \ --minimum-apply-seconds 0 \ --output-dir "{{ parallel_dir }}/benchmarks/quick-results" install-basic: basic "{{ meson_bin }}" install -C "{{ basic_dir }}" install-serial: serial "{{ meson_bin }}" install -C "{{ serial_dir }}" install-parallel: parallel "{{ meson_bin }}" install -C "{{ parallel_dir }}" fetch: "{{ meson_bin }}" subprojects download