diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 245e1d1afb..516cd386dc 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -89,7 +89,8 @@ jobs: arch: [default, complex] runs-on: [self-hosted, Linux] container: - image: ubuntu:latest + # TODO: set to 'ubuntu:latest' + image: ubuntu:noble outputs: sdist_conclusion: ${{ steps.report_sdist.outputs.conclusion }} env: @@ -477,7 +478,8 @@ jobs: name: Build and test Firedrake (Linux CUDA) runs-on: [self-hosted, Linux, gpu] container: - image: ubuntu:latest + # TODO: set to 'ubuntu:latest' + image: ubuntu:noble options: --gpus all if: inputs.test_gpu env: diff --git a/docs/Makefile b/docs/Makefile index 409e73fe86..da681bcad0 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -43,7 +43,7 @@ help: TARGETS = html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext -GENERATED_FILES = source/team.rst source/demos source/element_list.csv source/apt_deps.txt source/homebrew_deps.txt source/minimal_apt_deps.txt source/petsc_configure_options.txt +GENERATED_FILES = source/team.rst source/demos source/element_list.csv source/apt_deps.txt source/homebrew_deps.txt source/petsc_configure_options.txt publishpdf: env FIREDRAKE_MANUAL_RELEASE=`date +%Y-%m` $(MAKE) latexpdf @@ -86,26 +86,19 @@ source/team.rst: source/team2.py source/apt_deps.txt: python3 ../scripts/firedrake-configure \ - --package-manager apt-x86_64 \ + --os ubuntu24.04-x86_64 \ --show-system-packages > source/apt_deps.tmp mv source/apt_deps.tmp source/apt_deps.txt source/homebrew_deps.txt: python3 ../scripts/firedrake-configure \ - --package-manager brew-arm64 \ + --os macos-arm64 \ --show-system-packages > source/homebrew_deps.tmp mv source/homebrew_deps.tmp source/homebrew_deps.txt -source/minimal_apt_deps.txt: - python3 ../scripts/firedrake-configure \ - --package-manager apt-x86_64 \ - --show-minimal-system-packages > source/minimal_apt_deps.tmp - mv source/minimal_apt_deps.tmp source/minimal_apt_deps.txt - - source/petsc_configure_options.txt: python3 ../scripts/firedrake-configure \ - --no-package-manager \ + --os unknown \ --show-petsc-configure-options > source/petsc_configure_options.tmp mv source/petsc_configure_options.tmp source/petsc_configure_options.txt diff --git a/docs/source/install.rst b/docs/source/install.rst index a589196516..424880764a 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -119,10 +119,9 @@ ensure that these system dependencies are in place. Some of the dependencies downloaded by PETSc ``configure`` by passing additional flags like ``--download-mpich`` or ``--download-openblas`` (run ``./configure --help | less`` to see what is available). To give you a guide as to what system dependencies are -needed, on Ubuntu they are: +needed, on Ubuntu they are:: -.. literalinclude:: minimal_apt_deps.txt - :language: text + build-essential flex gfortran git ninja-build pkg-config python3-dev python3-pip .. _install_petsc: @@ -157,15 +156,15 @@ do the following steps: If you are using one of the :ref:`officially supported distributions` then these configure options will include paths to system packages so PETSc can correctly find and -link against them. If you are not then you should pass the ``--no-package-manager`` +link against them. If you are not then you should pass the ``--os unknown`` flag to obtain a set of configure options where ``firedrake-configure`` pessimistically assumes that no external packages are available, and hence need to be downloaded and compiled from source:: - $ python3 ../firedrake-configure --no-package-manager --show-petsc-configure-options | xargs -L1 ./configure + $ python3 ../firedrake-configure --os unknown --show-petsc-configure-options | xargs -L1 ./configure For the default build, running ``firedrake-configure`` with -``--no-package-manager`` will produce the flags: +``--os unknown`` will produce the flags: .. literalinclude:: petsc_configure_options.txt :language: text diff --git a/scripts/firedrake-configure b/scripts/firedrake-configure index c854cdc5e6..865dd8eed6 100755 --- a/scripts/firedrake-configure +++ b/scripts/firedrake-configure @@ -10,94 +10,111 @@ # As a matter of policy, new package managers and archs should only be added to # this file if they are *tested in CI*. -# Start by checking the Python version, older Pythons may not be able to run -# this script. import sys +import time -def stdout(msg: str, **kwargs) -> None: - """Write to stdout.""" - print(msg, file=sys.stdout, **kwargs) +def print_and_stop(msg: str) -> None: + """Print a message to stdout and stop the script.""" + print(msg, file=sys.stdout, end="") + exit(0) -def stderr(msg: str, **kwargs) -> None: - """Write to stderr. +def error(msg: str): + """Print an error message to stderr and stop the script. To make it distinct in the terminal output, messages are prefixed with 'ERROR: '. """ - print(f"ERROR: {msg}", file=sys.stderr, **kwargs) + print(f"ERROR: {msg}", file=sys.stderr) + # wait so users have a chance to see the message before it gets swamped by stdout + time.sleep(3) + exit(1) -def abort() -> None: - """Terminate the script.""" - exit(1) +def warn(msg: str): + """Print a warning message to stderr. + + To make it distinct in the terminal output, messages are prefixed with 'WARNING: '. + + """ + print(f"WARNING: {msg}", file=sys.stderr) + # wait so users have a chance to see the message before it gets swamped by stdout + time.sleep(1) +# Start by checking the Python version, older Pythons may not be able to run +# this script. MINIMUM_PYTHON_VERSION = "3.10" if sys.version < MINIMUM_PYTHON_VERSION: - stderr(f"Firedrake requires Python {MINIMUM_PYTHON_VERSION} or greater") - abort() + error(f"Firedrake requires Python {MINIMUM_PYTHON_VERSION} or greater") import argparse +import dataclasses import enum import os import platform -import subprocess -from collections.abc import Sequence -from typing import Optional - +from collections.abc import Mapping, Sequence -class PackageManager(enum.Enum): - LINUX_APT_X86_64 = "apt-x86_64" - LINUX_APT_AARCH64 = "apt-aarch64" - MACOS_HOMEBREW_ARM64 = "brew-arm64" - - -LINUX_APT_X86_64 = PackageManager.LINUX_APT_X86_64 -LINUX_APT_AARCH64 = PackageManager.LINUX_APT_AARCH64 -MACOS_HOMEBREW_ARM64 = PackageManager.MACOS_HOMEBREW_ARM64 - - -class GPUArch(enum.Enum): - NO_GPU = "none" - CUDA = "cuda" - - -NO_GPU = GPUArch.NO_GPU -CUDA = GPUArch.CUDA - - -class FiredrakeArch(enum.Enum): - DEFAULT = "default" - COMPLEX = "complex" - - -ARCH_DEFAULT = FiredrakeArch.DEFAULT -ARCH_COMPLEX = FiredrakeArch.COMPLEX +# Attributes that we expect to change occasionally SUPPORTED_PETSC_VERSION = "v3.25.0" # CUDA 13.1 is currently not supported by GPU drivers on Firedrake CI systems. SUPPORTED_CUDA_VERSION = "13.0" -CUDA_ARCH_MAP = { - "aarch64": "sbsa" -} +def main(): + parser = make_parser() + args = parser.parse_args() -# Contains the URL to a deb package that will enable vendor-specific software development -# repositories, or an empty string if none are required. -EXTRA_LINUX_APT_PKG_URL = { - NO_GPU: "", - CUDA: f"https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/{CUDA_ARCH_MAP.get(platform.machine(), platform.machine())}/cuda-keyring_1.1-1_all.deb", -} + if args.no_package_manager: + warn( + "Passing '--no-package-manager' is deprecated, please set '--os unknown' instead" + ) + args.os = OS.UNKNOWN + os_ = args.os if args.os else detect_os() + + arch_key = (os_, args.scalar_type, args.gpu_arch) + arch_key_str = f"({', '.join(f'{k.__class__.__name__}: {k.name}' for k in arch_key)})" + if arch_key in OFFICIAL_ARCHS: + arch = OFFICIAL_ARCHS[arch_key] + elif arch_key in COMMUNITY_ARCHS: + arch = COMMUNITY_ARCHS[arch_key] + warn( + "You have selected a community-maintained Firedrake configuration, " + f"if you encounter issues please contact {arch.maintainer}" + ) + else: + error( + f"Firedrake configuration not found for option set '{arch_key_str}', " + "please consider passing '--os unknown' or building manually" + ) + + if args.show_system_packages: + try: + arch.show_system_packages() + except InvalidConfigurationError: + error( + "Don't know what system dependencies to install for this arch " + f"'{arch_key_str}', please install them manually" + ) + elif args.show_petsc_configure_options: + arch.show_petsc_configure_options() + elif args.show_petsc_version: + print_and_stop(SUPPORTED_PETSC_VERSION) + elif args.show_extra_repo_pkg_url: + arch.show_url() + else: + assert args.show_env + arch.show_env() -def main(): +def make_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( - description="""Print out the configuration options needed to install Firedrake + description="""\ +Print out the configuration options needed to install Firedrake. This script takes in arguments declaring the operating system, target configuration (termed 'ARCH') and install step (installing system packages, @@ -110,585 +127,724 @@ that are used inside PETSc 'configure' instead of building from source. Please see https://firedrakeproject.org/install for more information.""" ) + package_manager_group = parser.add_mutually_exclusive_group() package_manager_group.add_argument( - "--package-manager", - choices=[pm.value for pm in PackageManager], + "--os", + "--package-manager", # old alias + choices=list(OS), + type=OS, required=False, - help="The system package manager, if not provided 'firedrake-configure' " + help="The operating system, if not provided 'firedrake-configure' " "will attempt to guess it.", ) + # old alias for '--os unknown' package_manager_group.add_argument( "--no-package-manager", action="store_true", required=False, - help="Do not attempt to use a system package manager.", + help="(Deprecated) Equivalent to '--os unknown'.", ) + parser.add_argument( - "--arch", - choices=[arch.value for arch in FiredrakeArch], - default=ARCH_DEFAULT, - help="The target configuration to install.", + "--scalar-type", + "--arch", # old alias + choices=list(ScalarType), + type=ScalarType, + default=ScalarType.DEFAULT, + help="PETSc scalar type.", ) parser.add_argument( "--gpu-arch", - choices=[arch.value for arch in GPUArch], + choices=list(GPUPlatform), + type=GPUPlatform, default="none", help=( "Target GPU architecture. WARNING: This is an experimental feature. " "GPU support in Firedrake is currently very limited." ), ) + cmd_group = parser.add_mutually_exclusive_group(required=True) cmd_group.add_argument( "--show-system-packages", - "--sysdeps", # alias action="store_true", help=( "Print out the system packages Firedrake needs including those " "expected by PETSc." ), ) - cmd_group.add_argument( - "--show-minimal-system-packages", - action="store_true", - help=( - "Print out the minimal system packages Firedrake needs to build. " - "The user must install these." - ), - ) cmd_group.add_argument( "--show-petsc-configure-options", - "--petscconf", # alias action="store_true", help="Print out arguments to pass to PETSc configure.", ) cmd_group.add_argument( "--show-petsc-version", - "--petscver", # alias action="store_true", help="Print out the officially supported PETSc version tag.", ) cmd_group.add_argument( "--show-env", - "--env", # alias action="store_true", help="Print out the environment variables that need to be exported to install Firedrake.", ) + # TODO: This is specific to particular archs, probably not the right design + # choice to enable for all. cmd_group.add_argument( "--show-extra-repo-pkg-url", - "--repopkgurl", action="store_true", help="Print out the URL of any package required to enable non-OS repo access for this build", ) - args = parser.parse_args() - if args.package_manager is not None: - assert not args.no_package_manager - package_manager = PackageManager(args.package_manager) - elif args.no_package_manager: - package_manager = None - else: - package_manager = sniff_package_manager() - arch = FiredrakeArch(args.arch) - - gpu_arch = GPUArch(args.gpu_arch) - if gpu_arch != NO_GPU and package_manager == MACOS_HOMEBREW_ARM64: - stderr( - "GPU-compatible PETSc builds are currently only supported" - "on Linux" - ) - abort() - - if args.show_system_packages: - if package_manager is None: - stderr( - "Cannot install Firedrake dependencies without a package manager, " - "please install them manually" - ) - abort() - stdout(" ".join(SYSTEM_PACKAGES[package_manager, arch, gpu_arch]), end="") - elif args.show_minimal_system_packages: - if package_manager is None: - stderr( - "Cannot install Firedrake dependencies without a package manager, " - "please install them manually" - ) - abort() - stdout(" ".join(MINIMAL_SYSTEM_PACKAGES[package_manager]), end="") - elif args.show_petsc_configure_options: - stdout(" ".join(PETSC_CONFIGURE_OPTIONS[package_manager, arch, gpu_arch]), end="") - elif args.show_petsc_version: - stdout(SUPPORTED_PETSC_VERSION, end="") - elif args.show_extra_repo_pkg_url: - stdout(EXTRA_LINUX_APT_PKG_URL[gpu_arch], end="") - else: - assert args.show_env - stdout(" ".join(ENVIRONMENT_VARS[package_manager, arch, gpu_arch]), end="") + return parser -def sniff_package_manager() -> Optional[PackageManager]: +def detect_os() -> "OS": if platform.system() == "Linux": - if has_apt(): - if platform.machine() == "x86_64": - return LINUX_APT_X86_64 - elif platform.machine() == "aarch64": - return LINUX_APT_AARCH64 + try: + os_info = platform.freedesktop_os_release() + except OSError: + pass + else: + if os_info["NAME"] == "Ubuntu": + if os_info["VERSION_ID"] == "24.04": + if platform.machine() == "x86_64": + return OS.UBUNTU_2404_X86_64 + elif platform.machine() == "aarch64": + return OS.UBUNTU_2404_AARCH64 + elif platform.system() == "Darwin": - if has_homebrew(): - if platform.machine() == "arm64": - return MACOS_HOMEBREW_ARM64 - stderr( - "No package manager detected, if you want to configure Firedrake without " - "any system packages please pass '--no-package-manager'" + if platform.machine() == "arm64": + return OS.MACOS_ARM64 + + error( + "Cannot identify operating system, if you want to configure Firedrake " + "without any system packages please pass '--os unknown'" ) - abort() - - -def has_apt() -> bool: - try: - subprocess.run(["apt", "--version"], capture_output=True) - return True - except FileNotFoundError: - return False - except: # noqa: E722 - stderr("Unexpected error occurred searching for apt") - abort() - - -def has_homebrew() -> bool: - try: - subprocess.run(["brew", "--version"], capture_output=True) - return True - except FileNotFoundError: - return False - except: # noqa: E722 - stderr("Unexpected error occurred searching for homebrew") - abort() - - -MINIMAL_LINUX_APT_PACKAGES = ( - "build-essential", - "flex", - "gfortran", - "git", - "ninja-build", - "pkg-config", - "python3-dev", - "python3-pip", -) - -BASE_LINUX_APT_PACKAGES = ( - MINIMAL_LINUX_APT_PACKAGES + ("bison", "cmake", "libopenblas-dev", "libopenmpi-dev") -) - -PETSC_EXTRAS_COMMON_APT_PACKAGES = ( - "libfftw3-dev", - "libfftw3-mpi-dev", - "libhwloc-dev", - "libhdf5-mpi-dev", - "libmumps-ptscotch-dev", - "libmetis-dev", - "libnetcdf-dev", - "libpnetcdf-dev", - "libptscotch-dev", - "libscalapack-openmpi-dev", -) - -PETSC_EXTRAS_LINUX_APT_NOGPU_PACKAGES = PETSC_EXTRAS_COMMON_APT_PACKAGES + ( - "libsuitesparse-dev", - "libsuperlu-dev", - "libsuperlu-dist-dev", -) - -cuda_ver_str = SUPPORTED_CUDA_VERSION.replace(".", "-") - -PETSC_EXTRAS_LINUX_APT_CUDA_PACKAGES = PETSC_EXTRAS_COMMON_APT_PACKAGES + ( - f"cuda-compat-{cuda_ver_str}", - f"cuda-nvtx-{cuda_ver_str}", - f"cuda-cudart-dev-{cuda_ver_str}", - f"cuda-command-line-tools-{cuda_ver_str}", - f"cuda-minimal-build-{cuda_ver_str}", - f"cuda-libraries-dev-{cuda_ver_str}", - f"cuda-nvml-dev-{cuda_ver_str}", - f"libnpp-dev-{cuda_ver_str}", - f"libcusparse-dev-{cuda_ver_str}", - f"libcublas-dev-{cuda_ver_str}", -) - -LINUX_APT_PACKAGES_NOGPU = BASE_LINUX_APT_PACKAGES + PETSC_EXTRAS_LINUX_APT_NOGPU_PACKAGES - -LINUX_APT_PACKAGES_CUDA = BASE_LINUX_APT_PACKAGES + PETSC_EXTRAS_LINUX_APT_CUDA_PACKAGES - -MINIMAL_MACOS_HOMEBREW_PACKAGES = ( - "autoconf", - "automake", - "boost", - "gcc", - "libtool", - "make", - "ninja", - "pkg-config", - "python", -) - -BASE_MACOS_HOMEBREW_PACKAGES = ( - MINIMAL_MACOS_HOMEBREW_PACKAGES + ("cmake", "openblas", "openmpi") -) - -PETSC_EXTRAS_MACOS_HOMEBREW_PACKAGES = ( - "fftw", - "hwloc", - "hdf5-mpi", - "metis", - "pnetcdf", - "scalapack", - "suitesparse", - "zlib", -) - -MACOS_HOMEBREW_PACKAGES = ( - BASE_MACOS_HOMEBREW_PACKAGES + PETSC_EXTRAS_MACOS_HOMEBREW_PACKAGES -) - -MINIMAL_SYSTEM_PACKAGES = { - LINUX_APT_X86_64: MINIMAL_LINUX_APT_PACKAGES, - LINUX_APT_AARCH64: MINIMAL_LINUX_APT_PACKAGES, - MACOS_HOMEBREW_ARM64: MINIMAL_MACOS_HOMEBREW_PACKAGES, -} -SYSTEM_PACKAGES = { - (LINUX_APT_X86_64, ARCH_DEFAULT, NO_GPU): LINUX_APT_PACKAGES_NOGPU, - (LINUX_APT_X86_64, ARCH_COMPLEX, NO_GPU): LINUX_APT_PACKAGES_NOGPU, - (LINUX_APT_AARCH64, ARCH_DEFAULT, NO_GPU): LINUX_APT_PACKAGES_NOGPU, - (LINUX_APT_AARCH64, ARCH_COMPLEX, NO_GPU): LINUX_APT_PACKAGES_NOGPU, - (MACOS_HOMEBREW_ARM64, ARCH_DEFAULT, NO_GPU): MACOS_HOMEBREW_PACKAGES, - (MACOS_HOMEBREW_ARM64, ARCH_COMPLEX, NO_GPU): MACOS_HOMEBREW_PACKAGES, - (LINUX_APT_X86_64, ARCH_DEFAULT, CUDA): LINUX_APT_PACKAGES_CUDA, - (LINUX_APT_AARCH64, ARCH_DEFAULT, CUDA): LINUX_APT_PACKAGES_CUDA, -} -COMMON_PETSC_CONFIGURE_OPTIONS = ( - "--with-c2html=0", - "--with-debugging=0", - "--with-fortran-bindings=0", - "--with-shared-libraries=1", - "--with-strict-petscerrorcode", -) - - -class PetscPackageAction(enum.IntEnum): - PETSC_AUTODETECT = enum.auto() - PETSC_DOWNLOAD = enum.auto() - - -# Placeholder value to use when we want PETSc to autodetect the package -PETSC_AUTODETECT = PetscPackageAction.PETSC_AUTODETECT - -# Placeholder value to use when we want PETSc to download the package -PETSC_DOWNLOAD = PetscPackageAction.PETSC_DOWNLOAD - - -# For each package and architecture there are a number of different types of input: -# 1. PETSC_AUTODETECT - PETSc will be able to find the package itself -# 2. PETSC_DOWNLOAD - a suitable system package is not available, PETSc configure -# will download and install it -# 3. str - the location of the package root directory (containing 'include' and -# 'lib' subdirectories) -# 4. tuple[str, tuple[str, ...]] - a 2-tuple consisting of the includes directory -# (location of the header files) and a collection of library files that PETSc needs. -PetscSpecValueType = PetscPackageAction | str | tuple[str | None, tuple[str, ...]] -PetscSpecsDictType = dict[str, dict[PackageManager, PetscSpecValueType]] - -PETSC_EXTERNAL_PACKAGE_SPECS_COMMON: PetscSpecsDictType = { - "bison": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "fftw": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "hdf5": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "hwloc": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "hypre": { - LINUX_APT_X86_64: PETSC_DOWNLOAD, - LINUX_APT_AARCH64: PETSC_DOWNLOAD, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "metis": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "mumps": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "netcdf": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "pnetcdf": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "ptscotch": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "scalapack": { - LINUX_APT_X86_64: (None, ("-lscalapack-openmpi",)), - LINUX_APT_AARCH64: (None, ("-lscalapack-openmpi",)), - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "zlib": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew/opt/zlib", - }, -} +class OS(enum.Enum): + UBUNTU_2404_X86_64 = "ubuntu24.04-x86_64" + UBUNTU_2404_AARCH64 = "ubuntu24.04-aarch64" + MACOS_ARM64 = "macos-arm64" + UNKNOWN = "unknown" -PETSC_EXTERNAL_PACKAGE_SPECS_NOGPU: PetscSpecsDictType = ( - PETSC_EXTERNAL_PACKAGE_SPECS_COMMON - | { - "suitesparse": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "superlu_dist": { - LINUX_APT_X86_64: PETSC_AUTODETECT, - LINUX_APT_AARCH64: PETSC_AUTODETECT, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - } -) - -PETSC_EXTERNAL_PACKAGE_SPECS_CUDA: PetscSpecsDictType = ( - PETSC_EXTERNAL_PACKAGE_SPECS_COMMON - | { - "suitesparse": { - LINUX_APT_X86_64: PETSC_DOWNLOAD, - LINUX_APT_AARCH64: PETSC_DOWNLOAD, - MACOS_HOMEBREW_ARM64: "/opt/homebrew", - }, - "superlu_dist": { - LINUX_APT_X86_64: PETSC_DOWNLOAD, - LINUX_APT_AARCH64: PETSC_DOWNLOAD, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - "umpire": { - LINUX_APT_X86_64: PETSC_DOWNLOAD, - LINUX_APT_AARCH64: PETSC_DOWNLOAD, - MACOS_HOMEBREW_ARM64: PETSC_DOWNLOAD, - }, - } -) - -COMMON_PETSC_EXTERNAL_PACKAGES = ( - "bison", - "fftw", - "hdf5", - "hwloc", - "metis", - "mumps", - "netcdf", - "pnetcdf", - "ptscotch", - "scalapack", - "suitesparse", - "superlu_dist", - "zlib", -) - -PETSC_EXTRA_EXTERNAL_PACKAGES_CUDA = ("umpire",) - - -def prepare_external_package_configure_options( - external_packages: Sequence[str], - package_manager: PackageManager | None = None, - gpu_arch: GPUArch = NO_GPU, -) -> tuple[str, ...]: - configure_options = [] - for external_package in external_packages: - if package_manager is None: - # Don't know anything about the system, download everything - package_spec = PETSC_DOWNLOAD - else: - if gpu_arch == NO_GPU: - package_spec = PETSC_EXTERNAL_PACKAGE_SPECS_NOGPU[external_package][package_manager] - elif gpu_arch == CUDA: - package_spec = PETSC_EXTERNAL_PACKAGE_SPECS_CUDA[external_package][package_manager] - - if package_spec == PETSC_AUTODETECT: - # PETSc will find the package for us - configure_options.append(f"--with-{external_package}") - elif package_spec == PETSC_DOWNLOAD: - # Package not provided by package manager, download it instead - configure_options.append(f"--download-{external_package}") - elif isinstance(package_spec, str): - # Package is installed in a 'sensible' way to /include and - # /lib but PETSc does not know so we have to provide it - configure_options.append(f"--with-{external_package}-dir={package_spec}") - else: - # Package is installed but not findable, have to provide paths - # to headers and libraries - (include_dir, libs) = package_spec - if include_dir is not None: - configure_options.append(f"--with-{external_package}-include={include_dir}") - if len(libs) >= 1: - configure_options.append(f"--with-{external_package}-lib={','.join(libs)}") - return tuple(configure_options) - - -def get_petsc_arch(arch: FiredrakeArch, gpu_arch: GPUArch) -> str: - arr = ["arch", "firedrake", arch.value] - if gpu_arch != NO_GPU: - arr.append(gpu_arch.value) - return "-".join(arr) - - -def prepare_configure_options( - package_manager: Optional[PackageManager], - arch: FiredrakeArch, - gpu_arch: GPUArch, -) -> tuple[str, ...]: - configure_options = list(COMMON_PETSC_CONFIGURE_OPTIONS) - configure_options.append(f"PETSC_ARCH={get_petsc_arch(arch, gpu_arch)}") - - # include/link flags - if package_manager in (LINUX_APT_X86_64, LINUX_APT_AARCH64): - incdir = "/usr/include" - if package_manager == LINUX_APT_X86_64: - libdir = "/usr/lib/x86_64-linux-gnu" - elif package_manager == LINUX_APT_AARCH64: - libdir = "/usr/lib/aarch64-linux-gnu" - - includes = ( - f"{incdir}/hdf5/openmpi", - f"{incdir}/scotch", - ) - if gpu_arch == NO_GPU: - includes = includes + ( - f"{incdir}/superlu", - f"{incdir}/superlu-dist", - ) +class ScalarType(enum.Enum): + DEFAULT = "default" + COMPLEX = "complex" - libraries = ( - f"{libdir}/hdf5/openmpi", - ) - incflags = " " + " ".join([f"-I{inc}" for inc in includes]) - libflags = " " + " ".join([f"-L{lib}" for lib in libraries]) +class GPUPlatform(enum.Enum): + NO_GPU = "none" + CUDA = "cuda" - else: - incflags = "" - libflags = "" - - configure_options.extend([ - f"--COPTFLAGS='-O3 -march=native -mtune=native{incflags}{libflags}'", - f"--CXXOPTFLAGS='-O3 -march=native -mtune=native{incflags}{libflags}'", - ]) - # Fortran flags - if package_manager == MACOS_HOMEBREW_ARM64: - # -march=native and -mtune=native not available for FOPTFLAGS on macOS - configure_options.append(f"--FOPTFLAGS='-O3{incflags}{libflags}'") - # Avoid macos + openmpi + mumps segmentation violation issue; - # see https://github.com/firedrakeproject/firedrake/issues/4102 and https://github.com/firedrakeproject/firedrake/issues/4113. - configure_options.append("-download-mumps-avoid-mpi-in-place") - else: - configure_options.append(f"--FOPTFLAGS='-O3 -march=native -mtune=native{incflags}{libflags}'") - if arch == ARCH_COMPLEX: - configure_options.append("--with-scalar-type=complex") +class InvalidConfigurationError(Exception): + pass - if gpu_arch == CUDA: - configure_options.extend( - ["--with-cuda=1", "--with-openmp=1", "--with-cxx-dialect=c++17"] - ) - external_packages = list(COMMON_PETSC_EXTERNAL_PACKAGES) - if arch != ARCH_COMPLEX: - external_packages.append("hypre") - if gpu_arch == CUDA: - external_packages.extend(PETSC_EXTRA_EXTERNAL_PACKAGES_CUDA) - configure_options.extend( - prepare_external_package_configure_options( - external_packages, package_manager, gpu_arch - ) - ) - return tuple(configure_options) - - -PETSC_VALID_BUILD_COMBINATIONS = ( - (LINUX_APT_X86_64, ARCH_DEFAULT, NO_GPU), - (LINUX_APT_X86_64, ARCH_COMPLEX, NO_GPU), - (LINUX_APT_AARCH64, ARCH_DEFAULT, NO_GPU), - (LINUX_APT_AARCH64, ARCH_COMPLEX, NO_GPU), - (MACOS_HOMEBREW_ARM64, ARCH_DEFAULT, NO_GPU), - (MACOS_HOMEBREW_ARM64, ARCH_COMPLEX, NO_GPU), - (None, ARCH_DEFAULT, NO_GPU), - (None, ARCH_COMPLEX, NO_GPU), - (LINUX_APT_X86_64, ARCH_DEFAULT, CUDA), - (LINUX_APT_AARCH64, ARCH_DEFAULT, CUDA), - (None, ARCH_DEFAULT, CUDA), -) - - -PETSC_CONFIGURE_OPTIONS = { - (package_manager, arch, gpu_arch): prepare_configure_options( - package_manager, arch, gpu_arch - ) - for (package_manager, arch, gpu_arch) in PETSC_VALID_BUILD_COMBINATIONS -} +@dataclasses.dataclass(frozen=True, kw_only=True) +class Arch: + name: str + """Name of the configuration. + This will be prefixed by 'arch-firedrake-' when generating the PETSc arch name. -def prepare_environment_vars( - package_manager: Optional[PackageManager], - arch: FiredrakeArch, - gpu_arch: GPUArch, -) -> tuple[str, ...]: - vars = { - "PETSC_DIR": f"{os.getcwd()}/petsc", - "PETSC_ARCH": get_petsc_arch(arch, gpu_arch), - "HDF5_MPI": "ON", - } - if gpu_arch == CUDA: - vars["PATH"] = f"/usr/local/cuda/bin:{os.environ.get('PATH', '')}" - - if package_manager == MACOS_HOMEBREW_ARM64: - # On macOS h5py cannot find the HDF5 library without help - vars["HDF5_DIR"] = "/opt/homebrew" - elif package_manager is None: - # If package manager is 'None' then we expect PETSc to build HDF5 - vars["HDF5_DIR"] = f"{vars['PETSC_DIR']}/{vars['PETSC_ARCH']}" - - return tuple(f"{var}={value}" for var, value in vars.items()) - - -ENVIRONMENT_VARS = { - (package_manager, arch, gpu_arch): prepare_environment_vars( - package_manager, arch, gpu_arch - ) - for (package_manager, arch, gpu_arch) in PETSC_VALID_BUILD_COMBINATIONS + """ + system_packages: Sequence[str] | None = None + """System packages.""" + extra_petsc_configure_options: Sequence[str] = () + """Extra options passed to PETSc configure.""" + cflags: Sequence[str] = () + """CFLAGS used to compile PETSc and external packages.""" + cxxflags: Sequence[str] = () + """CXXFLAGS used to compile PETSc and external packages.""" + fflags: Sequence[str] = () + """FFLAGS used to compile PETSc and external packages.""" + include_dirs: Sequence[str] = () + """Extra include directories used during PETSc configure and install""" + library_dirs: Sequence[str] = () + """Extra library directories used during PETSc configure and install""" + extra_env_vars: Mapping[str, str] = dataclasses.field(default_factory=dict) + """Extra environment variables that need setting during Firedrake install. + + If the special strings '$PETSC_DIR', '$PETSC_ARCH' or '$PATH' are used then + these will be replaced. + + """ + extra_url: str | None = None + """The URL to a deb package that will enable vendor-specific software development + repositories, or None if not required. + """ + + common_petsc_configure_options = [ + "--with-c2html=0", + "--with-debugging=0", + "--with-fortran-bindings=0", + "--with-shared-libraries=1", + "--with-strict-petscerrorcode", + ] + + def show_system_packages(self) -> None: + if self.system_packages is None: + raise InvalidConfigurationError + else: + print_and_stop(" ".join(self.system_packages)) + + def show_petsc_configure_options(self) -> None: + include_dirs = [f"-I{idir}" for idir in self.include_dirs] + library_dirs = [f"-L{ldir}" for ldir in self.library_dirs] + cflags = " ".join((*self.cflags, *include_dirs, *library_dirs)) + cxxflags = " ".join((*self.cxxflags, *include_dirs, *library_dirs)) + fflags = " ".join((*self.fflags, *include_dirs, *library_dirs)) + opts = [ + f"PETSC_ARCH=arch-firedrake-{self.name}", + f"--COPTFLAGS='{cflags}'", + f"--CXXOPTFLAGS='{cxxflags}'", + f"--FOPTFLAGS='{fflags}'", + *self.common_petsc_configure_options, + *self.extra_petsc_configure_options, + ] + print_and_stop(" ".join(opts)) + + def show_url(self) -> None: + assert self.extra_url + print_and_stop(self.extra_url) + + def show_env(self) -> None: + # TODO: inspect the current directory and error if PETSc isn't found + petsc_dir = f"{os.getcwd()}/petsc" + petsc_arch = f"arch-firedrake-{self.name}" + + env = { + "PETSC_DIR": petsc_dir, + "PETSC_ARCH": petsc_arch, + "HDF5_MPI": "ON", + } + env |= self.extra_env_vars + + replace_mapping = { + "$PETSC_DIR": petsc_dir, + "$PETSC_ARCH": petsc_arch, + "$PATH": os.environ.get("PATH", ""), + } + + def replace_vars(value: str): + for from_, to in replace_mapping.items(): + value = value.replace(from_, to) + return value + + env_str = " ".join(f"{name}={replace_vars(value)}" for name, value in env.items()) + print_and_stop(env_str) + + +@dataclasses.dataclass(frozen=True, kw_only=True) +class CommunityArch(Arch): + maintainer: str + """Name of the person or team maintaining a particular arch.""" + last_modified: str + + +ArchKey = tuple[OS, ScalarType, GPUPlatform] + +# Configurations with official support that are tested in CI +OFFICIAL_ARCHS: Mapping[ArchKey, Arch] = { + + # Ubuntu 24.04 x86 + + (OS.UBUNTU_2404_X86_64, ScalarType.DEFAULT, GPUPlatform.NO_GPU): Arch( + name="default", + system_packages=[ + "bison", + "build-essential", + "cmake", + "flex", + "gfortran", + "git", + "ninja-build", + "pkg-config", + "python3-dev", + "python3-pip", + + # PETSc external packages + "libfftw3-dev", + "libfftw3-mpi-dev", + "libhwloc-dev", + "libhdf5-mpi-dev", + "libmumps-ptscotch-dev", + "libmetis-dev", + "libnetcdf-dev", + "libopenblas-dev", + "libopenmpi-dev", + "libpnetcdf-dev", + "libptscotch-dev", + "libscalapack-openmpi-dev", + "libsuitesparse-dev", + "libsuperlu-dev", + "libsuperlu-dist-dev", + ], + extra_petsc_configure_options=[ + "--with-bison", + "--with-fftw", + "--with-hdf5", + "--with-hwloc", + "--with-metis", + "--with-mumps", + "--with-netcdf", + "--with-pnetcdf", + "--with-ptscotch", + "--with-scalapack-lib=-lscalapack-openmpi", + "--with-suitesparse", + "--with-superlu_dist", + "--with-zlib", + "--download-hypre", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + include_dirs=[ + "/usr/include/hdf5/openmpi", + "/usr/include/scotch", + "/usr/include/superlu", + "/usr/include/superlu-dist", + ], + library_dirs=[ + "/usr/lib/x86_64-linux-gnu/hdf5/openmpi", + ], + ), + + (OS.UBUNTU_2404_X86_64, ScalarType.DEFAULT, GPUPlatform.CUDA): Arch( + name="default-cuda", + system_packages=[ + "bison", + "build-essential", + "cmake", + "flex", + "gfortran", + "git", + "ninja-build", + "pkg-config", + "python3-dev", + "python3-pip", + + # PETSc external packages + "libfftw3-dev", + "libfftw3-mpi-dev", + "libhwloc-dev", + "libhdf5-mpi-dev", + "libmumps-ptscotch-dev", + "libmetis-dev", + "libnetcdf-dev", + "libopenblas-dev", + "libopenmpi-dev", + "libpnetcdf-dev", + "libptscotch-dev", + "libscalapack-openmpi-dev", + + # CUDA packages + f"cuda-compat-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-nvtx-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-cudart-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-command-line-tools-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-minimal-build-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-libraries-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"cuda-nvml-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"libnpp-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"libcusparse-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + f"libcublas-dev-{SUPPORTED_CUDA_VERSION.replace('.', '-')}", + ], + extra_petsc_configure_options=[ + "--with-bison", + "--with-fftw", + "--with-hdf5", + "--with-hwloc", + "--with-metis", + "--with-mumps", + "--with-netcdf", + "--with-pnetcdf", + "--with-ptscotch", + "--with-scalapack-lib=-lscalapack-openmpi", + "--with-zlib", + "--download-hypre", + "--download-suitesparse", + "--download-superlu_dist", + + # CUDA options + "--with-cuda=1", + "--with-openmp=1", + "--with-cxx-dialect=c++17", + "--download-umpire", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + include_dirs=[ + "/usr/include/hdf5/openmpi", + "/usr/include/scotch", + "/usr/include/superlu", + "/usr/include/superlu-dist", + ], + library_dirs=[ + "/usr/lib/x86_64-linux-gnu/hdf5/openmpi", + ], + extra_env_vars={ + "PATH": "/usr/local/cuda/bin:$PATH", + }, + extra_url="https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb", + ), + + (OS.UBUNTU_2404_X86_64, ScalarType.COMPLEX, GPUPlatform.NO_GPU): Arch( + name="complex", + system_packages=[ + "bison", + "build-essential", + "cmake", + "flex", + "gfortran", + "git", + "ninja-build", + "pkg-config", + "python3-dev", + "python3-pip", + + # PETSc external packages + "libfftw3-dev", + "libfftw3-mpi-dev", + "libhwloc-dev", + "libhdf5-mpi-dev", + "libmumps-ptscotch-dev", + "libmetis-dev", + "libnetcdf-dev", + "libopenblas-dev", + "libopenmpi-dev", + "libpnetcdf-dev", + "libptscotch-dev", + "libscalapack-openmpi-dev", + "libsuitesparse-dev", + "libsuperlu-dev", + "libsuperlu-dist-dev", + ], + extra_petsc_configure_options=[ + "--with-scalar-type=complex", + "--with-bison", + "--with-fftw", + "--with-hdf5", + "--with-hwloc", + "--with-metis", + "--with-mumps", + "--with-netcdf", + "--with-pnetcdf", + "--with-ptscotch", + "--with-scalapack-lib=-lscalapack-openmpi", + "--with-suitesparse", + "--with-superlu_dist", + "--with-zlib", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + include_dirs=[ + "/usr/include/hdf5/openmpi", + "/usr/include/scotch", + "/usr/include/superlu", + "/usr/include/superlu-dist", + ], + library_dirs=[ + "/usr/lib/x86_64-linux-gnu/hdf5/openmpi", + ], + ), + + # Ubuntu 24.04 aarch64 + + (OS.UBUNTU_2404_AARCH64, ScalarType.DEFAULT, GPUPlatform.NO_GPU): Arch( + name="default", + system_packages=[ + "bison", + "build-essential", + "cmake", + "flex", + "gfortran", + "git", + "ninja-build", + "pkg-config", + "python3-dev", + "python3-pip", + + # PETSc external packages + "libfftw3-dev", + "libfftw3-mpi-dev", + "libhwloc-dev", + "libhdf5-mpi-dev", + "libmumps-ptscotch-dev", + "libmetis-dev", + "libnetcdf-dev", + "libopenblas-dev", + "libopenmpi-dev", + "libpnetcdf-dev", + "libptscotch-dev", + "libscalapack-openmpi-dev", + "libsuitesparse-dev", + "libsuperlu-dev", + "libsuperlu-dist-dev", + ], + extra_petsc_configure_options=[ + "--with-bison", + "--with-fftw", + "--with-hdf5", + "--with-hwloc", + "--with-metis", + "--with-mumps", + "--with-netcdf", + "--with-pnetcdf", + "--with-ptscotch", + "--with-scalapack-lib=-lscalapack-openmpi", + "--with-suitesparse", + "--with-superlu_dist", + "--with-zlib", + "--download-hypre", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + include_dirs=[ + "/usr/include/hdf5/openmpi", + "/usr/include/scotch", + "/usr/include/superlu", + "/usr/include/superlu-dist", + ], + library_dirs=[ + "/usr/lib/aarch64-linux-gnu/hdf5/openmpi", + ], + ), + + (OS.UBUNTU_2404_AARCH64, ScalarType.COMPLEX, GPUPlatform.NO_GPU): Arch( + name="complex", + system_packages=[ + "bison", + "build-essential", + "cmake", + "flex", + "gfortran", + "git", + "ninja-build", + "pkg-config", + "python3-dev", + "python3-pip", + + # PETSc external packages + "libfftw3-dev", + "libfftw3-mpi-dev", + "libhwloc-dev", + "libhdf5-mpi-dev", + "libmumps-ptscotch-dev", + "libmetis-dev", + "libnetcdf-dev", + "libopenblas-dev", + "libopenmpi-dev", + "libpnetcdf-dev", + "libptscotch-dev", + "libscalapack-openmpi-dev", + "libsuitesparse-dev", + "libsuperlu-dev", + "libsuperlu-dist-dev", + ], + extra_petsc_configure_options=[ + "--with-scalar-type=complex", + "--with-bison", + "--with-fftw", + "--with-hdf5", + "--with-hwloc", + "--with-metis", + "--with-mumps", + "--with-netcdf", + "--with-pnetcdf", + "--with-ptscotch", + "--with-scalapack-lib=-lscalapack-openmpi", + "--with-suitesparse", + "--with-superlu_dist", + "--with-zlib", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + include_dirs=[ + "/usr/include/hdf5/openmpi", + "/usr/include/scotch", + "/usr/include/superlu", + "/usr/include/superlu-dist", + ], + library_dirs=[ + "/usr/lib/aarch64-linux-gnu/hdf5/openmpi", + ], + ), + + # macOS arm64 + + (OS.MACOS_ARM64, ScalarType.DEFAULT, GPUPlatform.NO_GPU): Arch( + name="default", + system_packages=[ + "autoconf", + "automake", + "boost", + "gcc", + "libtool", + "make", + "ninja", + "pkg-config", + "python", + + # PETSc external packages + "cmake", + "fftw", + "hwloc", + "hdf5-mpi", + "metis", + "openblas", + "openmpi", + "pnetcdf", + "scalapack", + "suitesparse", + "zlib", + ], + extra_petsc_configure_options=[ + # External packages + "--with-fftw-dir=/opt/homebrew", + "--with-hdf5-dir=/opt/homebrew", + "--with-hwloc-dir=/opt/homebrew", + "--with-metis-dir=/opt/homebrew", + "--with-pnetcdf-dir=/opt/homebrew", + "--with-scalapack-dir=/opt/homebrew", + "--with-suitesparse-dir=/opt/homebrew", + "--with-zlib-dir=/opt/homebrew", + "--download-bison", + "--download-hypre", + "--download-mumps", + "--download-netcdf", + "--download-ptscotch", + "--download-superlu_dist", + + # Avoid macos + openmpi + mumps segmentation violation issue; + # see https://github.com/firedrakeproject/firedrake/issues/4102 and https://github.com/firedrakeproject/firedrake/issues/4113. + "-download-mumps-avoid-mpi-in-place", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3"], + extra_env_vars={"HDF5_DIR": "/opt/homebrew"}, + ), + + (OS.MACOS_ARM64, ScalarType.COMPLEX, GPUPlatform.NO_GPU): Arch( + name="complex", + system_packages=[ + "autoconf", + "automake", + "boost", + "gcc", + "libtool", + "make", + "ninja", + "pkg-config", + "python", + + # PETSc external packages + "cmake", + "fftw", + "hwloc", + "hdf5-mpi", + "metis", + "openblas", + "openmpi", + "pnetcdf", + "scalapack", + "suitesparse", + "zlib", + ], + extra_petsc_configure_options=[ + "--with-scalar-type=complex", + + # External packages + "--with-fftw-dir=/opt/homebrew", + "--with-hdf5-dir=/opt/homebrew", + "--with-hwloc-dir=/opt/homebrew", + "--with-metis-dir=/opt/homebrew", + "--with-pnetcdf-dir=/opt/homebrew", + "--with-scalapack-dir=/opt/homebrew", + "--with-suitesparse-dir=/opt/homebrew", + "--with-zlib-dir=/opt/homebrew", + "--download-bison", + "--download-mumps", + "--download-netcdf", + "--download-ptscotch", + "--download-superlu_dist", + + # Avoid macos + openmpi + mumps segmentation violation issue; + # see https://github.com/firedrakeproject/firedrake/issues/4102 and https://github.com/firedrakeproject/firedrake/issues/4113. + "-download-mumps-avoid-mpi-in-place", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3"], + extra_env_vars={"HDF5_DIR": "/opt/homebrew"}, + ), + + # Sane default configurations for unknown platforms + + (OS.UNKNOWN, ScalarType.DEFAULT, GPUPlatform.NO_GPU): Arch( + name="default", + extra_petsc_configure_options=[ + "--download-bison", + "--download-fftw", + "--download-hdf5", + "--download-hwloc", + "--download-hypre", + "--download-metis", + "--download-mumps", + "--download-netcdf", + "--download-pnetcdf", + "--download-ptscotch", + "--download-scalapack", + "--download-suitesparse", + "--download-superlu_dist", + "--download-zlib", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + extra_env_vars={"HDF5_DIR": "$PETSC_DIR/$PETSC_ARCH"}, + ), + + (OS.UNKNOWN, ScalarType.COMPLEX, GPUPlatform.NO_GPU): Arch( + name="complex", + extra_petsc_configure_options=[ + "--with-scalar-type=complex", + "--download-bison", + "--download-fftw", + "--download-hdf5", + "--download-hwloc", + "--download-hypre", + "--download-metis", + "--download-mumps", + "--download-netcdf", + "--download-pnetcdf", + "--download-ptscotch", + "--download-scalapack", + "--download-suitesparse", + "--download-superlu_dist", + "--download-zlib", + ], + cflags=["-O3", "-march=native", "-mtune=native"], + cxxflags=["-O3", "-march=native", "-mtune=native"], + fflags=["-O3", "-march=native", "-mtune=native"], + extra_env_vars={"HDF5_DIR": "$PETSC_DIR/$PETSC_ARCH"}, + ), } +# 'Best effort' configurations that are not tested in CI +COMMUNITY_ARCHS: Mapping[ArchKey, CommunityArch] = {} + + if __name__ == "__main__": main()