diff --git a/config.yaml b/config.yaml index 0922ead..1a3e930 100644 --- a/config.yaml +++ b/config.yaml @@ -39,6 +39,15 @@ uenvs: santis: [gh200] balfrin: [a100] develop: False + icon-dsl: + "25.8": + recipes: + gh200: '25.8/gh200' + a100: '25.8/a100' + deploy: + santis: [gh200] + balfrin: [a100] + develop: False mch: "v7": recipes: diff --git a/recipes/icon-dsl/25.8/a100/compilers.yaml b/recipes/icon-dsl/25.8/a100/compilers.yaml new file mode 100644 index 0000000..f456b5a --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/compilers.yaml @@ -0,0 +1,9 @@ +bootstrap: + spec: gcc@12.3 +gcc: + specs: + - gcc@13 +llvm: + requires: gcc@13 + specs: + - nvhpc@25.1 diff --git a/recipes/icon-dsl/25.8/a100/config.yaml b/recipes/icon-dsl/25.8/a100/config.yaml new file mode 100644 index 0000000..ac4ba9c --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/config.yaml @@ -0,0 +1,7 @@ +name: icon-dsl +store: /user-environment +spack: + repo: https://github.com/spack/spack.git + commit: releases/v0.23 +modules: false +description: Build and runtime dependencies for ICON-DSL diff --git a/recipes/icon-dsl/25.8/a100/environments.yaml b/recipes/icon-dsl/25.8/a100/environments.yaml new file mode 100644 index 0000000..3a399e0 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/environments.yaml @@ -0,0 +1,47 @@ +myenv: + compiler: + - toolchain: gcc + spec: gcc + - toolchain: llvm + spec: nvhpc + mpi: + spec: cray-mpich@8.1.30%nvhpc + gpu: cuda + specs: + # icon4py deps + - python@3.11 + - py-cupy +cuda cuda_arch=90 + - ghex +python +cuda cuda_arch=90 + - py-mpi4py + - icon4py@icon_20250328 + # icon deps + - boost + - cuda@12.4 + - eccodes@2.36.4%nvhpc +tools +fortran +aec +openmp jp2k=jasper + - cosmo-eccodes-definitions@2.36.0.3 + - hdf5%nvhpc +szip +hl +fortran +mpi + - netcdf-c@4.9.2%nvhpc + - netcdf-cxx4@4.3.1%nvhpc + - netcdf-fortran@4.6.1%nvhpc + - osu-micro-benchmarks@5.9%nvhpc + - openblas + # for validation + - cdo + # everything needed for nccl on SS11 + - nccl + - nccl-tests + # extras + - libfyaml + - zlib-ng + - cmake + unify: true + variants: + - +mpi + - +cuda + - cuda_arch=80 + views: + default: + link: roots + uenv: + prefix_paths: + LD_LIBRARY_PATH: [lib, lib64] diff --git a/recipes/icon-dsl/25.8/a100/extra/reframe.yaml b/recipes/icon-dsl/25.8/a100/extra/reframe.yaml new file mode 100644 index 0000000..363f809 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/extra/reframe.yaml @@ -0,0 +1,6 @@ +default: + features: [osu-micro-benchmarks, mpi, serial, openmp] + cc: mpicc + cxx: mpic++ + ftn: mpifort + activation: /user-environment/env/default/activate.sh diff --git a/recipes/icon-dsl/25.8/a100/modules.yaml b/recipes/icon-dsl/25.8/a100/modules.yaml new file mode 100644 index 0000000..a4010ae --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/modules.yaml @@ -0,0 +1,26 @@ +modules: + # Paths to check when creating modules for all module sets + prefix_inspections: + bin: + - PATH + lib: + - LD_LIBRARY_PATH + lib64: + - LD_LIBRARY_PATH + + default: + arch_folder: false + # Where to install modules + roots: + tcl: /snap/modules + tcl: + all: + autoload: run + hash_length: 0 + hide_implicits: true + exclude: + - '%gcc@7.5.0' + - '%gcc@12' + - 'gcc %gcc@7.5.0' + projections: + all: '{name}/{version}' diff --git a/recipes/icon-dsl/25.8/a100/pre-install b/recipes/icon-dsl/25.8/a100/pre-install new file mode 100644 index 0000000..ba88283 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/pre-install @@ -0,0 +1,12 @@ +#!/bin/bash + +packages=("cosmo-eccodes-definitions") +SPACK_C2SM_TAG="v0.22.2.1" + +git clone -b ${SPACK_C2SM_TAG} https://github.com/C2SM/spack-c2sm.git + +for package in "${packages[@]}"; do + cp -r spack-c2sm/repos/c2sm/packages/"${package}" store/repo/packages +done + +rm -rf spack-c2sm diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/cmake_install_rpath.patch b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/cmake_install_rpath.patch new file mode 100644 index 0000000..7e2b250 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/cmake_install_rpath.patch @@ -0,0 +1,11 @@ +--- a/cmake/ecbuild_append_to_rpath.cmake ++++ b/cmake/ecbuild_append_to_rpath.cmake +@@ -31,7 +31,7 @@ function( _path_append var path ) + else() + list( FIND ${var} ${path} _found ) + if( _found EQUAL "-1" ) +- set( ${var} "${${var}}:${path}" PARENT_SCOPE ) ++ set( ${var} "${${var}};${path}" PARENT_SCOPE ) + endif() + endif() + endfunction() diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/openjpeg_jasper.patch b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/openjpeg_jasper.patch new file mode 100644 index 0000000..5793f56 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/openjpeg_jasper.patch @@ -0,0 +1,39 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -43,6 +43,18 @@ ecbuild_add_option( FEATURE JPG + DESCRIPTION "support for JPG decoding/encoding" + DEFAULT ON + ) ++# Options related to JPG. The Jasper and OpenJPEG libraries ++ecbuild_add_option( FEATURE JPG_LIBJASPER ++ DESCRIPTION "Support for JPG decoding/encoding with the Jasper library" ++ CONDITION ENABLE_JPG ++ DEFAULT ON ++) ++ecbuild_add_option( FEATURE JPG_LIBOPENJPEG ++ DESCRIPTION "Support for JPG decoding/encoding with the OpenJPEG library" ++ CONDITION ENABLE_JPG ++ DEFAULT ON ++) ++ + + ecbuild_add_option( FEATURE PNG + DESCRIPTION "support for PNG decoding/encoding" +@@ -144,7 +156,7 @@ if( ENABLE_JPG ) + + find_package( OpenJPEG ) + +- if( JASPER_FOUND ) ++ if( JASPER_FOUND AND ENABLE_JPG_LIBJASPER ) + list( APPEND ECCODES_TPLS Jasper ) + set( HAVE_JPEG 1 ) + set( HAVE_LIBJASPER 1 ) +@@ -152,7 +164,7 @@ if( ENABLE_JPG ) + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" JASPER_VERSION_MAJOR "${JASPER_VERSION_STRING}") + endif() + +- if( OPENJPEG_FOUND ) ++ if( OPENJPEG_FOUND AND ENABLE_JPG_LIBOPENJPEG ) + list( APPEND ECCODES_TPLS OpenJPEG ) + set( HAVE_JPEG 1 ) + set( HAVE_LIBOPENJPEG 1 ) diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/package.py new file mode 100644 index 0000000..aeb4692 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/package.py @@ -0,0 +1,385 @@ +# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + + +from spack.package import * + +_definitions = { + # German Meteorological Service (Deutscher Wetterdienst, DWD): + "edzw": { + "conflicts": {"when": "@:2.19.1,2.22.0,2.24.0:"}, + "resources": [ + { + "when": "@2.20.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.20.0-1.tar.gz", + "sha256": "a92932f8a13c33cba65d3a33aa06c7fb4a37ed12a78e9abe2c5e966402b99af4", + }, + { + "when": "@2.21.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.21.0-3.tar.bz2", + "sha256": "046f1f6450abb3b44c31dee6229f4aab06ca0d3576e27e93e05ccb7cd6e2d9d9", + }, + { + "when": "@2.22.1", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.22.1-1.tar.bz2", + "sha256": "be73102a0dcabb236bacd2a70c7b5475f673fda91b49e34df61bef0fa5ad3389", + }, + { + "when": "@2.23.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.23.0-4.tar.bz2", + "sha256": "c5db32861c7d23410aed466ffef3ca661410d252870a3949442d3ecb176aa338", + }, + ], + } +} + + +class Eccodes(CMakePackage): + """ecCodes is a package developed by ECMWF for processing meteorological + data in GRIB (1/2), BUFR (3/4) and GTS header formats.""" + + homepage = "https://software.ecmwf.int/wiki/display/ECC/ecCodes+Home" + url = "https://confluence.ecmwf.int/download/attachments/45757960/eccodes-2.2.0-Source.tar.gz?api=v2" + git = "https://github.com/ecmwf/eccodes.git" + list_url = "https://confluence.ecmwf.int/display/ECC/Releases" + + maintainers("skosukhin", "victoria-cherkas", "dominichofer", "climbfuji") + + license("Apache-2.0") + + version("develop", branch="develop") + version("2.36.4", + sha256="198ccb26e8df96544c668ea6853ea153535ab78b10c43339a678f271337aa0da", + url="https://github.com/ecmwf/eccodes/archive/refs/tags/2.36.4.tar.gz" + ) + version("2.34.0", sha256="3cd208c8ddad132789662cf8f67a9405514bfefcacac403c0d8c84507f303aba") + version("2.33.0", sha256="bdcec8ce63654ec6803400c507f01220a9aa403a45fa6b5bdff7fdcc44fd7daf") + version("2.32.1", sha256="ad2ac1bf36577b1d35c4a771b4d174a06f522a1e5ef6c1f5e53a795fb624863e") + version("2.32.0", sha256="b57e8eeb0eba0c05d66fda5527c4ffa84b5ab35c46bcbc9a2227142973ccb8e6") + version("2.31.0", sha256="808ecd2c11fbf2c3f9fc7a36f8c2965b343f3151011b58a1d6e7cc2e6b3cac5d") + version("2.25.0", sha256="8975131aac54d406e5457706fd4e6ba46a8cc9c7dd817a41f2aa64ce1193c04e") + version("2.24.2", sha256="c60ad0fd89e11918ace0d84c01489f21222b11d6cad3ff7495856a0add610403") + version("2.23.0", sha256="cbdc8532537e9682f1a93ddb03440416b66906a4cc25dec3cbd73940d194bf0c") + version("2.22.1", sha256="75c7ee96469bb30b0c8f7edbdc4429ece4415897969f75c36173545242bc9e85") + version("2.21.0", sha256="da0a0bf184bb436052e3eae582defafecdb7c08cdaab7216780476e49b509755") + version("2.20.0", sha256="207a3d7966e75d85920569b55a19824673e8cd0b50db4c4dac2d3d52eacd7985") + version("2.19.1", sha256="9964bed5058e873d514bd4920951122a95963128b12f55aa199d9afbafdd5d4b") + version("2.18.0", sha256="d88943df0f246843a1a062796edbf709ef911de7269648eef864be259e9704e3") + version("2.13.0", sha256="c5ce1183b5257929fc1f1c8496239e52650707cfab24f4e0e1f1a471135b8272") + version("2.5.0", sha256="18ab44bc444168fd324d07f7dea94f89e056f5c5cd973e818c8783f952702e4e") + version("2.2.0", sha256="1a4112196497b8421480e2a0a1164071221e467853486577c4f07627a702f4c3") + + # we are still using spack v0.21 v0.22, so comment these out for now + #depends_on("c", type="build") # generated + #depends_on("cxx", type="build") # generated + #depends_on("fortran", type="build") # generated + + variant("tools", default=False, description="Build the command line tools") + variant("netcdf", default=False, description="Enable GRIB to NetCDF conversion tool") + variant( + "jp2k", + default="openjpeg", + values=("openjpeg", "jasper", "none"), + description="Specify JPEG2000 decoding/encoding backend", + ) + variant("png", default=False, description="Enable PNG support for decoding/encoding") + variant( + "aec", default=True, description="Enable Adaptive Entropy Coding for decoding/encoding" + ) + variant("pthreads", default=False, description="Enable POSIX threads") + variant("openmp", default=False, description="Enable OpenMP threads") + variant( + "memfs", default=False, description="Enable memory based access to definitions/samples" + ) + variant("fortran", default=False, description="Enable the Fortran support") + variant("shared", default=True, description="Build shared versions of the libraries") + + variant( + "extra_definitions", + values=any_combination_of(*_definitions.keys()), + description="List of extra definitions to install", + ) + + depends_on("netcdf-c", when="+netcdf") + # Cannot be built with openjpeg@2.0.x. + depends_on("openjpeg@1.5.0:1.5,2.1.0:2.3", when="jp2k=openjpeg") + # Additional constraint for older versions. + depends_on("openjpeg@:2.1", when="@:2.16 jp2k=openjpeg") + + with when("jp2k=jasper"): + depends_on("jasper") + # jasper 3.x compat from commit 86f0b35f1a8492cb16f82fb976a0a5acd2986ac2 + depends_on("jasper@:2", when="@:2.25.0") + + depends_on("libpng", when="+png") + depends_on("libaec", when="+aec") + # Can be built with Python 2 or Python 3. + depends_on("python", when="+memfs", type="build") + + depends_on("cmake@3.6:", type="build") + depends_on("cmake@3.12:", when="@2.19:", type="build") + + # TODO: ecbuild was only used for the @develop branch + # however, testing 2.36.4, it appears to be a requirement. + # this might be because they package the software differently in GitHub + # (they normally provide releases as tar balls on Confluence) + depends_on("ecbuild", type="build") + #depends_on("ecbuild", type="build", when="@develop") + + conflicts("+openmp", when="+pthreads", msg="Cannot enable both POSIX threads and OMP") + + conflicts( + "+netcdf", + when="~tools", + msg="Cannot enable the NetCDF conversion tool " "when the command line tools are disabled", + ) + + conflicts( + "~tools", + when="@:2.18.0", + msg="The command line tools can be disabled " "only starting version 2.19.0", + ) + + for center, definitions in _definitions.items(): + kwargs = definitions.get("conflicts", None) + if kwargs: + conflicts("extra_definitions={0}".format(center), **kwargs) + for kwargs in definitions.get("resources", []): + resource( + name=center, + destination="spack-definitions", + placement="definitions.{0}".format(center), + **kwargs, + ) + + # Enforce linking against the specified JPEG2000 backend, see also + # https://github.com/ecmwf/eccodes/commit/2c10828495900ff3d80d1e570fe96c1df16d97fb + patch("openjpeg_jasper.patch", when="@:2.16") + + # CMAKE_INSTALL_RPATH must be a semicolon-separated list. + patch("cmake_install_rpath.patch", when="@:2.10") + + # Fix a bug preventing cmake from finding NetCDF: + patch( + "https://github.com/ecmwf/ecbuild/commit/3916c7d22575c45166fcc89edcbe02a6e9b81aa2.patch?full_index=1", + sha256="9dcc4affaaa850d4b7247baa939d0f9ffedea132369f1afc3f248dbf720386c9", + when="@:2.4.0+netcdf", + ) + + @when("%nag+fortran") + def patch(self): + # A number of Fortran source files assume that the kinds of integer and + # real variables are specified in bytes. However, the NAG compiler + # accepts such code only with an additional compiler flag -kind=byte. + # We do not simply add the flag because all user applications would + # have to be compiled with this flag too, which goes against one of the + # purposes of using the NAG compiler: make sure the code does not + # contradict the Fortran standards. The following logic could have been + # implemented as regular patch files, which would, however, be quite + # large. We would also have to introduce several versions of each patch + # file to support different versions of the package. + + patch_kind_files = [ + "fortran/eccodes_f90_head.f90", + "fortran/eccodes_f90_tail.f90", + "fortran/grib_f90_head.f90", + "fortran/grib_f90_tail.f90", + "fortran/grib_types.f90", + ] + + patch_unix_ext_files = [] + + if self.run_tests: + patch_kind_files.extend( + [ + "examples/F90/grib_print_data.f90", + "examples/F90/grib_print_data_static.f90", + # Files that need patching only when the extended regression + # tests are enabled, which we disable unconditionally: + # 'examples/F90/bufr_attributes.f90', + # 'examples/F90/bufr_expanded.f90', + # 'examples/F90/bufr_get_keys.f90', + # 'examples/F90/bufr_read_scatterometer.f90', + # 'examples/F90/bufr_read_synop.f90', + # 'examples/F90/bufr_read_temp.f90', + # 'examples/F90/bufr_read_tempf.f90', + # 'examples/F90/bufr_read_tropical_cyclone.f90', + # 'examples/F90/grib_clone.f90', + # 'examples/F90/grib_get_data.f90', + # 'examples/F90/grib_nearest.f90', + # 'examples/F90/grib_precision.f90', + # 'examples/F90/grib_read_from_file.f90', + # 'examples/F90/grib_samples.f90', + # 'examples/F90/grib_set_keys.f90' + ] + ) + + patch_unix_ext_files.extend( + [ + "examples/F90/bufr_ecc-1284.f90", + "examples/F90/grib_set_data.f90", + "examples/F90/grib_set_packing.f90", + # Files that need patching only when the extended regression + # tests are enabled, which we disable unconditionally: + # 'examples/F90/bufr_copy_data.f90', + # 'examples/F90/bufr_get_string_array.f90', + # 'examples/F90/bufr_keys_iterator.f90', + # 'examples/F90/get_product_kind.f90', + # 'examples/F90/grib_count_messages_multi.f90' + ] + ) + + kwargs = {"string": False, "backup": False, "ignore_absent": True} + + # Return the kind and not the size: + filter_file( + r"(^\s*kind_of_double\s*=\s*)(\d{1,2})(\s*$)", + "\\1kind(real\\2)\\3", + "fortran/grib_types.f90", + **kwargs, + ) + filter_file( + r"(^\s*kind_of_\w+\s*=\s*)(\d{1,2})(\s*$)", + "\\1kind(x\\2)\\3", + "fortran/grib_types.f90", + **kwargs, + ) + + # Replace integer kinds: + for size, r in [(2, 4), (4, 9), (8, 18)]: + filter_file( + r"(^\s*integer\((?:kind=)?){0}(\).*)".format(size), + "\\1selected_int_kind({0})\\2".format(r), + *patch_kind_files, + **kwargs, + ) + + # Replace real kinds: + for size, p, r in [(4, 6, 37), (8, 15, 307)]: + filter_file( + r"(^\s*real\((?:kind=)?){0}(\).*)".format(size), + "\\1selected_real_kind({0}, {1})\\2".format(p, r), + *patch_kind_files, + **kwargs, + ) + + # Enable getarg and exit subroutines: + filter_file( + r"(^\s*program\s+\w+)(\s*$)", + "\\1; use f90_unix_env; use f90_unix_proc\\2", + *patch_unix_ext_files, + **kwargs, + ) + + @property + def libs(self): + libraries = [] + + query_parameters = self.spec.last_query.extra_parameters + + if "shared" in query_parameters: + shared = True + elif "static" in query_parameters: + shared = False + else: + shared = "+shared" in self.spec + + # Return Fortran library if requested: + return_fortran = "fortran" in query_parameters + # Return C library if either requested or the Fortran library is not + # requested (to avoid overlinking) or the static libraries are + # requested: + return_c = "c" in query_parameters or not (return_fortran and shared) + # Return MEMFS library only if enabled and the static libraries are + # requested: + return_memfs = "+memfs" in self.spec and not shared + + if return_fortran: + libraries.append("libeccodes_f90") + + if return_c: + libraries.append("libeccodes") + + if return_memfs: + libraries.append("libeccodes_memfs") + + libs = find_libraries(libraries, root=self.prefix, shared=shared, recursive=True) + + if libs and len(libs) == len(libraries): + return libs + + msg = "Unable to recursively locate {0} {1} libraries in {2}" + raise spack.error.NoLibrariesError( + msg.format("shared" if shared else "static", self.spec.name, self.spec.prefix) + ) + + @run_before("cmake") + def check_fortran(self): + if "+fortran" in self.spec and self.compiler.fc is None: + raise InstallError("Fortran interface requires a Fortran compiler!") + + def cmake_args(self): + jp2k = self.spec.variants["jp2k"].value + + args = [ + self.define_from_variant("ENABLE_BUILD_TOOLS", "tools"), + self.define_from_variant("ENABLE_NETCDF", "netcdf"), + self.define("ENABLE_JPG", jp2k != "none"), + self.define("ENABLE_JPG_LIBJASPER", jp2k == "jasper"), + self.define("ENABLE_JPG_LIBOPENJPEG", jp2k == "openjpeg"), + self.define_from_variant("ENABLE_PNG", "png"), + self.define_from_variant("ENABLE_AEC", "aec"), + self.define_from_variant("ENABLE_ECCODES_THREADS", "pthreads"), + self.define_from_variant("ENABLE_ECCODES_OMP_THREADS", "openmp"), + self.define_from_variant("ENABLE_MEMFS", "memfs"), + self.define( + "ENABLE_PYTHON{0}".format("2" if self.spec.satisfies("@2.20.0:") else ""), False + ), + self.define_from_variant("ENABLE_FORTRAN", "fortran"), + self.define("BUILD_SHARED_LIBS", "BOTH" if "+shared" in self.spec else "OFF"), + self.define("ENABLE_TESTS", self.run_tests), + # Examples are not installed and are just part of the test suite: + self.define("ENABLE_EXAMPLES", self.run_tests), + # Unconditionally disable the extended regression tests, since they + # download additional data (~134MB): + self.define("ENABLE_EXTRA_TESTS", False), + ] + + if self.spec.satisfies("+netcdf"): + # Prevent possible overriding by environment variables NETCDF_ROOT, NETCDF_DIR, and + # NETCDF_PATH: + args.append(self.define("NETCDF_PATH", self.spec["netcdf-c"].prefix)) + # Prevent overriding by environment variable HDF5_ROOT (starting version 2.14.0, + # ecCodes is shipped with ecBuild 3.1.0+, which does not seem to rely on the HDF5_ROOT + # variable): + if self.spec.satisfies("@:2.13"): + args.append(self.define("HDF5_ROOT", self.spec["hdf5"].prefix)) + + if jp2k == "openjpeg": + args.append(self.define("OPENJPEG_PATH", self.spec["openjpeg"].prefix)) + + if self.spec.satisfies("+png"): + args.append(self.define("ZLIB_ROOT", self.spec["zlib-api"].prefix)) + + if self.spec.satisfies("+aec"): + # Prevent overriding by environment variables AEC_DIR and AEC_PATH: + args.append(self.define("AEC_DIR", self.spec["libaec"].prefix)) + + return args + + @run_after("install") + def install_extra_definitions(self): + for center in self.spec.variants["extra_definitions"].value: + if center != "none": + center_dir = "definitions.{0}".format(center) + install_tree( + join_path(self.stage.source_path, "spack-definitions", center_dir), + join_path(self.prefix.share.eccodes, center_dir), + ) + + def check(self): + # https://confluence.ecmwf.int/display/ECC/ecCodes+installation + with working_dir(self.build_directory): + ctest() diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/readme.md b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/readme.md new file mode 100644 index 0000000..9678342 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/eccodes/readme.md @@ -0,0 +1 @@ +copied from mainline spack November 5 2024 so that we can add eccodes 2.36.0 for mch production diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/ghex/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/ghex/package.py new file mode 100644 index 0000000..8f50e28 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/ghex/package.py @@ -0,0 +1,93 @@ +from spack.package import * + + +class Ghex(CMakePackage, CudaPackage, ROCmPackage): + """GHEX is a generic halo-exchange library.""" + + homepage = "https://github.com/ghex-org/GHEX" + url = "https://github.com/ghex-org/GHEX/archive/refs/tags/v0.3.0.tar.gz" + git = "https://github.com/ghex-org/GHEX.git" + maintainers = ["boeschf"] + + version("0.4.1", tag="v0.4.1", submodules=True) + version("0.4.0", tag="v0.4.0", submodules=True) + version("0.3.0", tag="v0.3.0", submodules=True) + version("master", branch="master", submodules=True) + + depends_on("cxx", type="build") + + generator("ninja") + + backends = ("mpi", "ucx", "libfabric") + variant( + "backend", + default="mpi", + description="Transport backend", + values=backends, + multi=False, + ) + variant("xpmem", default=False, description="Use xpmem shared memory") + variant("python", default=True, description="Build Python bindings") + + depends_on("cmake@3.21:", type="build") + depends_on("mpi") + depends_on("boost") + depends_on("xpmem", when="+xpmem", type=("build", "run")) + + depends_on("oomph") + for backend in backends: + depends_on(f"oomph backend={backend}", when=f"backend={backend}") + depends_on("oomph+cuda", when="+cuda") + depends_on("oomph+rocm", when="+rocm") + depends_on("oomph@0.3:", when="@0.3:") + + conflicts("+cuda+rocm") + + with when("+python"): + extends("python") + depends_on("python@3.7:", type="build") + depends_on("py-pip", type="build") + depends_on("py-pybind11", type="build") + depends_on("py-mpi4py", type=("build", "run")) + depends_on("py-numpy", type=("build", "run")) + + depends_on("py-pytest", when="+python", type=("test")) + + def cmake_args(self): + spec = self.spec + + args = [ + self.define("GHEX_USE_BUNDLED_LIBS", True), + self.define("GHEX_USE_BUNDLED_GRIDTOOLS", True), + self.define("GHEX_USE_BUNDLED_GTEST", self.run_tests), + self.define("GHEX_USE_BUNDLED_OOMPH", False), + self.define( + "GHEX_TRANSPORT_BACKEND", spec.variants["backend"].value.upper() + ), + self.define_from_variant("GHEX_USE_XPMEM", "xpmem"), + self.define_from_variant("GHEX_BUILD_PYTHON_BINDINGS", "python"), + self.define("GHEX_WITH_TESTING", self.run_tests), + ] + + if spec.satisfies("+python"): + args.append(self.define("GHEX_PYTHON_LIB_PATH", python_platlib)) + + if self.run_tests and spec.satisfies("^openmpi"): + args.append(self.define("MPIEXEC_PREFLAGS", "--oversubscribe")) + + if "+cuda" in spec and spec.variants["cuda_arch"].value != "none": + arch_str = ";".join(spec.variants["cuda_arch"].value) + args.append(self.define("CMAKE_CUDA_ARCHITECTURES", arch_str)) + args.append(self.define("GHEX_USE_GPU", True)) + args.append(self.define("GHEX_GPU_TYPE", "NVIDIA")) + + if "+rocm" in spec and spec.variants["amdgpu_target"].value != "none": + arch_str = ";".join(spec.variants["amdgpu_target"].value) + args.append(self.define("CMAKE_HIP_ARCHITECTURES", arch_str)) + args.append(self.define("GHEX_USE_GPU", True)) + args.append(self.define("GHEX_GPU_TYPE", "AMD")) + + if spec.satisfies("~cuda~rocm"): + args.append(self.define("GHEX_USE_GPU", False)) + + return args diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/cmake_install_path.patch b/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/cmake_install_path.patch new file mode 100644 index 0000000..fa6fde1 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/cmake_install_path.patch @@ -0,0 +1,27 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d5420e0..35dbe56 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -105,11 +105,11 @@ install(FILES ${PROJECT_BINARY_DIR}/include/hwmalloc/config.hpp + install(EXPORT HWMALLOC-targets + FILE HWMALLOC-targets.cmake + NAMESPACE HWMALLOC:: +- DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/HWMALLOCConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/HWMALLOCConfig.cmake +- INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + write_basic_package_version_file(HWMALLOCConfigVersion.cmake + VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +@@ -120,7 +120,7 @@ install( + ${CMAKE_CURRENT_BINARY_DIR}/HWMALLOCConfigVersion.cmake + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindNUMA.cmake + DESTINATION +- ${CMAKE_INSTALL_LIBDIR}/cmake) ++ ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + export(EXPORT HWMALLOC-targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/HWMALLOC-targets.cmake") diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/package.py new file mode 100644 index 0000000..c656dc1 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/hwmalloc/package.py @@ -0,0 +1,52 @@ +from spack.package import * + + +class Hwmalloc(CMakePackage, CudaPackage, ROCmPackage): + """HWMALLOC is a allocator which supports memory registration for e.g. remote memory access""" + + homepage = "https://github.com/ghex-org/hwmalloc" + url = "https://github.com/ghex-org/hwmalloc/archive/refs/tags/v0.3.0.tar.gz" + git = "https://github.com/ghex-org/hwmalloc.git" + maintainers = ["boeschf"] + + version("0.3.0", sha256="d4d4ac6087a806600d79fb62c02719ca3d58a412968fe1ef4a2fd58d9e7ee950") + version("0.2.0", sha256="734758a390a3258b86307e4aef50a7ca2e5d0e2e579f18aeefcd05397e114419") + version("0.1.0", sha256="06e9bfcef0ecce4d19531ccbe03592b502d1281c7a092bc0ff51ca187899b21c") + version("master", branch="master") + + depends_on("cxx", type="build") + + generator("ninja") + + depends_on("numactl", type=("build", "run")) + depends_on("boost", type=("build")) + depends_on("cmake@3.19:", type="build") + + variant( + "numa-throws", + default=False, + description="True if numa_tools may throw during initialization", + ) + variant("numa-local", default=True, description="Use numa_tools for local node allocations") + variant("logging", default=False, description="print logging info to cerr") + + patch("cmake_install_path.patch", when="@:0.3.0", level=1) + + def cmake_args(self): + args = [ + self.define_from_variant("HWMALLOC_NUMA_THROWS", "numa-throws"), + self.define_from_variant("HWMALLOC_NUMA_FOR_LOCAL", "numa-local"), + self.define_from_variant("HWMALLOC_ENABLE_LOGGING", "logging"), + self.define("HWMALLOC_WITH_TESTING", self.run_tests), + ] + + if "+cuda" in self.spec: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", True)) + args.append(self.define("HWMALLOC_DEVICE_RUNTIME", "cuda")) + elif "+rocm" in self.spec: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", True)) + args.append(self.define("HWMALLOC_DEVICE_RUNTIME", "hip")) + else: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", False)) + + return args diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/icon4py/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/icon4py/package.py new file mode 100644 index 0000000..9ee413e --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/icon4py/package.py @@ -0,0 +1,109 @@ +import json +import os +import pathlib + +import llnl +from llnl.util import tty +from spack import * + + +class Icon4py(Package): + extends("python") + depends_on("python@3.11:") + + depends_on("git") + depends_on("boost@1.85:+mpi+python", type=("build", "run")) + depends_on("uv@0.7:", type="build") + depends_on("bzip2", type="build") + depends_on("py-numpy") + depends_on("py-cffi") + depends_on("py-pybind11") + depends_on("py-nanobind") + depends_on("py-mpi4py") + depends_on("py-cupy +cuda") + depends_on("ghex +python +cuda") + + version( + "icon_20250328", + sha256="8573ef031d207438f549511e859f522c60163ea660aafea93ef4991b9010739a", + extension="zip", + ) + + def url_for_version(self, version): + return f"https://github.com/c2sm/icon4py/archive/refs/heads/{version}.zip" + + def install(self, spec, prefix): + uv = prepare_uv() + python_spec = spec["python"] + venv_path = prefix.share.venv + + tty.msg(f"creating venv using spack python at: {python_spec.command.path}") + uv( + "venv", + "--seed", + "--relocatable", + "--system-site-packages", + str(venv_path), + "--python", + python_spec.command.path, + ) + + tty.msg(f"grabbing spack installed packages (distributions)") + pip = Executable(venv_path.bin.pip) + spack_installed = get_installed_pkg(pip) + + tty.msg(f"installing missing packages") + uv( + "sync", + "--active", + "--extra", + "all", + "--extra", + "cuda12", + "--inexact", + "--no-editable", + "--python", + str(venv_path.bin.python), + *no_install_options([*spack_installed, "cupy-cuda12x", "ghex"]), + extra_env={"VIRTUAL_ENV": str(venv_path)}, + ) + + tty.msg(f"linking spack installed packages into venv") + pathlib.Path( + f"{venv_path.lib.python}{python_spec.version.up_to(2)}/site-packages/spack_installed.pth" + ).write_text(pythonpath_to_pth()) + + tty.msg(f"running py2fgen") + py2fgen = Executable(venv_path.bin.py2fgen) + py2fgen( + "icon4py.tools.py2fgen.wrappers.all_bindings", + "diffusion_init,diffusion_run,grid_init,solve_nh_init,solve_nh_run", + "icon4py_bindings", + "-o", + prefix.src, + extra_env={"VIRTUAL_ENV": str(venv_path)}, + ) + + +def prepare_uv(): + uv = which("uv") + uv.add_default_env("UV_NO_CACHE", "true") + uv.add_default_env("UV_NO_MANAGED_PYTHON", "true") + uv.add_default_env("UV_PYTHON_DOWNLOADS", "never") + return uv + + +def get_installed_pkg(pip): + return [ + item["name"] for item in json.loads(pip("list", "--format", "json", output=str)) + ] + + +def no_install_options(installed): + for name in installed: + yield "--no-install-package" + yield name + + +def pythonpath_to_pth(): + return "\n".join(os.environ["PYTHONPATH"].split(":")) diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.2.patch b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.2.patch new file mode 100644 index 0000000..5dc7e2e --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.2.patch @@ -0,0 +1,102 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ba19089..2ba222a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,12 @@ + cmake_minimum_required(VERSION 3.17) + # CMake version is set at 3.17 because of find_package(CUDAToolkit) + ++if (NOT ${CMAKE_VERSION} VERSION_LESS 3.27) ++ # new in 3.27: additionally use uppercase _ROOT ++ # environment and CMake variables for find_package ++ cmake_policy(SET CMP0144 NEW) ++endif() ++ + set(OOMPH_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + list(APPEND CMAKE_MODULE_PATH "${OOMPH_MODULE_PATH}") + +@@ -108,11 +114,11 @@ endif() + install(EXPORT oomph-targets + FILE oomph-targets.cmake + NAMESPACE oomph:: +- DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/oomphConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/oomphConfig.cmake +- INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + write_basic_package_version_file(oomphConfigVersion.cmake + VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +@@ -125,7 +131,7 @@ install( + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindUCX.cmake + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindPMIx.cmake + DESTINATION +- ${CMAKE_INSTALL_LIBDIR}/cmake) ++ ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + export(EXPORT oomph-targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/oomph-targets.cmake") +diff --git a/cmake/oomph_external_dependencies.cmake b/cmake/oomph_external_dependencies.cmake +index ec672b5..a578ef5 100644 +--- a/cmake/oomph_external_dependencies.cmake ++++ b/cmake/oomph_external_dependencies.cmake +@@ -31,17 +31,30 @@ endif() + # --------------------------------------------------------------------- + # google test setup + # --------------------------------------------------------------------- +-add_external_cmake_project( +- NAME googletest +- PATH ext/googletest +- INTERFACE_NAME ext-gtest +- LIBS libgtest.a libgtest_main.a +- CMAKE_ARGS +- "-DCMAKE_BUILD_TYPE=release" +- "-DBUILD_SHARED_LIBS=OFF" +- "-DBUILD_GMOCK=OFF") +-# on some systems we need link explicitly against threads +-if (TARGET ext-gtest) +- find_package (Threads) +- target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++cmake_dependent_option(OOMPH_USE_BUNDLED_GTEST "Use bundled googletest lib." ON ++ "OOMPH_USE_BUNDLED_LIBS" OFF) ++if (OOMPH_WITH_TESTING) ++ if(OOMPH_USE_BUNDLED_GTEST) ++ add_external_cmake_project( ++ NAME googletest ++ PATH ext/googletest ++ INTERFACE_NAME ext-gtest ++ LIBS libgtest.a libgtest_main.a ++ CMAKE_ARGS ++ "-DCMAKE_BUILD_TYPE=release" ++ "-DBUILD_SHARED_LIBS=OFF" ++ "-DBUILD_GMOCK=OFF") ++ # on some systems we need link explicitly against threads ++ if (TARGET ext-gtest) ++ find_package (Threads) ++ target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++ endif() ++ else() ++ # Use system provided google test ++ find_package(GTest REQUIRED) ++ add_library(ext-gtest INTERFACE) ++ if (${CMAKE_VERSION} VERSION_LESS "3.20.0") ++ target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++ else() ++ target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ endif() ++ endif() + endif() +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index 06d703a..5217bba 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -65,6 +65,7 @@ function(reg_parallel_test t_ lib n) + NAME ${t} + COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${n} ${MPIEXEC_PREFLAGS} + $ ${MPIEXEC_POSTFLAGS}) ++ set_tests_properties(${t} PROPERTIES RUN_SERIAL TRUE) + endfunction() + + if (OOMPH_WITH_MPI) diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.3.patch b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.3.patch new file mode 100644 index 0000000..aac73e8 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/install_0.3.patch @@ -0,0 +1,57 @@ +diff --git a/cmake/oomph_external_dependencies.cmake b/cmake/oomph_external_dependencies.cmake +index a578ef5..92de39b 100644 +--- a/cmake/oomph_external_dependencies.cmake ++++ b/cmake/oomph_external_dependencies.cmake +@@ -33,28 +33,30 @@ endif() + # --------------------------------------------------------------------- + cmake_dependent_option(OOMPH_USE_BUNDLED_GTEST "Use bundled googletest lib." ON + "OOMPH_USE_BUNDLED_LIBS" OFF) +-if(OOMPH_USE_BUNDLED_GTEST) +- add_external_cmake_project( +- NAME googletest +- PATH ext/googletest +- INTERFACE_NAME ext-gtest +- LIBS libgtest.a libgtest_main.a +- CMAKE_ARGS +- "-DCMAKE_BUILD_TYPE=release" +- "-DBUILD_SHARED_LIBS=OFF" +- "-DBUILD_GMOCK=OFF") +- # on some systems we need link explicitly against threads +- if (TARGET ext-gtest) +- find_package (Threads) +- target_link_libraries(ext-gtest INTERFACE Threads::Threads) +- endif() +-else() +- # Use system provided google test +- find_package(GTest REQUIRED) +- add_library(ext-gtest INTERFACE) +- if (${CMAKE_VERSION} VERSION_LESS "3.20.0") +- target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++if (OOMPH_WITH_TESTING) ++ if(OOMPH_USE_BUNDLED_GTEST) ++ add_external_cmake_project( ++ NAME googletest ++ PATH ext/googletest ++ INTERFACE_NAME ext-gtest ++ LIBS libgtest.a libgtest_main.a ++ CMAKE_ARGS ++ "-DCMAKE_BUILD_TYPE=release" ++ "-DBUILD_SHARED_LIBS=OFF" ++ "-DBUILD_GMOCK=OFF") ++ # on some systems we need link explicitly against threads ++ if (TARGET ext-gtest) ++ find_package (Threads) ++ target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++ endif() + else() +- target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ # Use system provided google test ++ find_package(GTest REQUIRED) ++ add_library(ext-gtest INTERFACE) ++ if (${CMAKE_VERSION} VERSION_LESS "3.20.0") ++ target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++ else() ++ target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ endif() + endif() + endif() diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/oomph/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/package.py new file mode 100644 index 0000000..3b320f9 --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/oomph/package.py @@ -0,0 +1,109 @@ +from spack.package import * + + +class Oomph(CMakePackage, CudaPackage, ROCmPackage): + """Oomph is a non-blocking callback-based point-to-point communication library.""" + + homepage = "https://github.com/ghex-org/oomph" + url = "https://github.com/ghex-org/oomph/archive/refs/tags/v0.2.0.tar.gz" + git = "https://github.com/ghex-org/oomph.git" + maintainers = ["boeschf"] + + version("0.4.0", sha256="e342c872dfe4832be047f172dc55c12951950c79da2630b071c61607ef913144") + version("0.3.0", sha256="61e346d1ba28a859745de47f37edce39c7f5c5e1aab716493dc964e158fd99ec") + version("0.2.0", sha256="135cdb856aa817c053b6af1617869dbcd0ee97d34607e78874dd775ea389434e") + version("0.1.0", sha256="0ff36db0a5f30ae1bb02f6db6d411ea72eadd89688c00f76b4e722bd5a9ba90b") + version("main", branch="main") + + depends_on("cxx", type="build") + depends_on("fortran", type="build", when="+fortran-bindings") + + generator("ninja") + + backends = ("mpi", "ucx", "libfabric") + variant( + "backend", default="mpi", description="Transport backend", values=backends, multi=False + ) + + variant("fortran-bindings", default=False, description="Build Fortran bindings") + with when("+fortran-bindings"): + variant( + "fortran-fp", + default="float", + description="Floating point type", + values=("float", "double"), + multi=False, + ) + variant("fortran-openmp", default=True, description="Compile with OpenMP") + + variant( + "enable-barrier", + default=True, + description="Enable thread barrier (disable for task based runtime)", + ) + + depends_on("hwmalloc+cuda", when="+cuda") + depends_on("hwmalloc+rocm", when="+rocm") + depends_on("hwmalloc", when="~cuda~rocm") + + with when("backend=ucx"): + depends_on("ucx+thread_multiple") + depends_on("ucx+cuda", when="+cuda") + depends_on("ucx+rocm", when="+rocm") + variant("use-pmix", default="False", description="Use PMIx to establish out-of-band setup") + variant("use-spin-lock", default="False", description="Use pthread spin locks") + depends_on("pmix", when="+use-pmix") + + libfabric_providers = ("cxi", "efa", "gni", "psm2", "tcp", "verbs") + with when("backend=libfabric"): + variant( + "libfabric-provider", + default="tcp", + description="fabric", + values=libfabric_providers, + multi=False, + ) + for provider in libfabric_providers: + depends_on(f"libfabric fabrics={provider}", when=f"libfabric-provider={provider}") + + depends_on("mpi") + depends_on("boost+thread") + + depends_on("googletest", type=("build","test")) + + patch("install_0.2.patch", when="@:0.2.0", level=1) + patch("install_0.3.patch", when="@0.3.0", level=1) + + def cmake_args(self): + args = [ + self.define_from_variant("OOMPH_BUILD_FORTRAN", "fortran-bindings"), + self.define_from_variant("OOMPH_FORTRAN_OPENMP", "fortran-openmp"), + self.define_from_variant("OOMPH_UCX_USE_PMI", "use-pmix"), + self.define_from_variant("OOMPH_UCX_USE_SPIN_LOCK", "use-spin-lock"), + self.define_from_variant("OOMPH_ENABLE_BARRIER", "enable-barrier"), + self.define("OOMPH_WITH_TESTING", self.run_tests), + self.define("OOMPH_GIT_SUBMODULE", False), + self.define("OOMPH_USE_BUNDLED_LIBS", False), + ] + + if self.run_tests and self.spec.satisfies("^openmpi"): + args.append(self.define("MPIEXEC_PREFLAGS", "--oversubscribe")) + + if self.spec.variants["fortran-bindings"].value == True: + args.append(self.define("OOMPH_FORTRAN_FP", self.spec.variants["fortran-fp"].value)) + + for backend in self.backends: + args.append( + self.define( + f"OOMPH_WITH_{backend.upper()}", self.spec.variants["backend"].value == backend + ) + ) + + if self.spec.satisfies("backend=libfabric"): + args.append( + self.define( + "OOMPH_LIBFABRIC_PROVIDER", self.spec.variants["libfabric-provider"].value + ) + ) + + return args diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/py-cupy/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/py-cupy/package.py new file mode 100644 index 0000000..e2be01e --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/py-cupy/package.py @@ -0,0 +1,145 @@ +# Copyright Spack Project Developers. See COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +import os + +from spack.package import * + + +class PyCupy(PythonPackage, CudaPackage, ROCmPackage): + """CuPy is an open-source array library accelerated with + NVIDIA CUDA. CuPy provides GPU accelerated computing with + Python. CuPy uses CUDA-related libraries including cuBLAS, + cuRand, cuSolver, cuSPARSE, cuFFT and NCCL to make + full use of the GPU architecture. + + This version does not use CudNN.""" + + homepage = "https://cupy.dev/" + pypi = "cupy/cupy-8.0.0.tar.gz" + + # version( + # "13.5.1", + # sha256="3dba2f30258463482d52deb420862fbbbaf2c446165a5e8d67377ac6cb5c0870", + # ) + version( + "13.1.0", + sha256="5caf62288481a27713384523623045380ff42e618be4245f478238ed1786f32d", + ) + version( + "12.1.0", + sha256="f6d31989cdb2d96581da12822e28b102f29e254427195c2017eac327869b7320", + ) + version( + "12.0.0", + sha256="61ddbbef73d50d606bd5087570645f3c91ec9176c2566784c1d486d6a3404545", + ) + version( + "11.6.0", + sha256="53dbb840072bb32d4bfbaa6bfa072365a30c98b1fcd1f43e48969071ad98f1a7", + ) + version( + "11.5.0", + sha256="4bc8565bded22cc89b210fd9fb48a5d5316f30701e12bb23852a60314e1f9f6e", + ) + version( + "11.4.0", + sha256="03d52b2626e02a3a2b46d714c1cd03e702c8fe33915fcca6ed8de5c539964f49", + ) + version( + "11.3.0", + sha256="d057cc2f73ecca06fae8b9c270d9e14116203abfd211a704810cc50a453b4c9e", + ) + version( + "11.2.0", + sha256="c33361f117a347a63f6996ea97446d17f1c038f1a1f533e502464235076923e2", + ) + + variant( + "all", default=False, description="Enable optional py-scipy, optuna, and cython" + ) + + depends_on("cxx", type="build") # generated + + depends_on("python@3.7:", when="@:11", type=("build", "run")) + depends_on("python@3.8:", when="@12:", type=("build", "run")) + depends_on("py-setuptools", type="build") + depends_on("py-cython@0.29.22:2", type="build") + depends_on("py-fastrlock@0.5:", type=("build", "run")) + depends_on("py-numpy@1.20:1.25", when="@:11", type=("build", "run")) + depends_on("py-numpy@1.20:1.26", when="@12:", type=("build", "run")) + depends_on("py-numpy@1.22:1.28", when="@13:", type=("build", "run")) + + depends_on("py-scipy@1.6:1.12", when="@:12+all", type=("build", "run")) + depends_on("py-scipy@1.7:1.13", when="@13:+all", type=("build", "run")) + depends_on("py-cython@0.29.22:2", when="+all", type=("build", "run")) + depends_on("py-optuna@2:", when="+all", type=("build", "run")) + + # Based on https://github.com/cupy/cupy/releases + depends_on("cuda@:11.9", when="@:11 +cuda") + depends_on("cuda@:12.1", when="@12:12.1.0 +cuda") + depends_on("cuda@:12.4", when="@13:13.4.1 +cuda") + depends_on("cuda@:12.9", when="@13.5.1: +cuda") + + for a in CudaPackage.cuda_arch_values: + depends_on( + "nccl +cuda cuda_arch={0}".format(a), when="+cuda cuda_arch={0}".format(a) + ) + + depends_on("cutensor", when="@:12.1.0 +cuda") + depends_on("cutensor@2.0.1.2", when="@13.1: +cuda") + + for _arch in ROCmPackage.amdgpu_targets: + arch_str = "amdgpu_target={0}".format(_arch) + rocm_str = "+rocm {0}".format(arch_str) + depends_on("rocprim {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocsolver {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocthrust {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocrand {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("hipcub {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipblas {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hiprand {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipsparse {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipfft {0}".format(rocm_str), when=rocm_str, type=("link")) + + depends_on("rccl", when="+rocm", type=("link")) + depends_on("roctracer-dev", when="+rocm", type=("link")) + depends_on("rocprofiler-dev", when="+rocm", type=("link")) + + conflicts("~cuda ~rocm") + conflicts("+cuda +rocm") + conflicts("+cuda cuda_arch=none") + + def setup_build_environment(self, env): + env.set("CUPY_NUM_BUILD_JOBS", make_jobs) + if self.spec.satisfies("+cuda"): + cuda_arch = self.spec.variants["cuda_arch"].value + arch_str = ";".join( + "arch=compute_{0},code=sm_{0}".format(i) for i in cuda_arch + ) + env.set("CUPY_NVCC_GENERATE_CODE", arch_str) + elif self.spec.satisfies("+rocm"): + spec = self.spec + + incs = { + "roctracer-dev": ["include/roctracer"], + "hiprand": ["include"], + "rocrand": ["include"], + "rocthrust": ["include"], + "rocprim": ["include"], + "hip": ["include", "include/hip"], + } + + inc_dirs = [] + for pkg, ds in incs.items(): + for d in ds: + p = os.path.join(spec[pkg].prefix, d) + if os.path.exists(p): + inc_dirs.append(p) + + env.set("CUPY_INCLUDE_PATH", ":".join(inc_dirs)) + + env.set("HIPCC", self.spec["hip"].hipcc) + env.set("ROCM_HOME", self.spec["hipcub"].prefix) + env.set("CUPY_INSTALL_USE_HIP", 1) diff --git a/recipes/icon-dsl/25.8/a100/repo/packages/uv/package.py b/recipes/icon-dsl/25.8/a100/repo/packages/uv/package.py new file mode 100644 index 0000000..6941eff --- /dev/null +++ b/recipes/icon-dsl/25.8/a100/repo/packages/uv/package.py @@ -0,0 +1,68 @@ +from spack.package import * + + +def translate_platform(platform_name: str) -> str: + if platform_name == "darwin": + return "apple-darwin" + elif platform_name == "linux": + return "unknown-linux-gnu" + return platform_name + + +def translate_arch(arch_name: str) -> str: + if arch_name in ["m1", "m2", "neoverse_v2"]: + return "aarch64" + if arch_name in ["zen3"]: + return "x86_64" + return arch_name + + +class Uv(Package): + """Install UV from binary releases""" + + url = "https://github.com/astral-sh/uv/releases/download/0.7.12/uv-aarch64-apple-darwin.tar.gz" + + version( + "0.7.12", + sha256="189108cd026c25d40fb086eaaf320aac52c3f7aab63e185bac51305a1576fc7e", + extension=".tar.gz", + ) + version( + "0.7.20", + sha256="675165f879d6833aa313ecb25ac44781e131933a984727e180b3218d2cd6c1e9", + extension=".tar.gz", + ) + + def url_for_version(self, version): + arch = translate_arch(self.spec.target) + platform = translate_platform(self.spec.platform) + return f"https://github.com/astral-sh/uv/releases/download/{version}/uv-{arch}-{platform}.tar.gz" + + def do_stage(self, mirror_only=False): + checksums = { + ("0.7.12", "apple-darwin", "aarch64"): ( + "189108cd026c25d40fb086eaaf320aac52c3f7aab63e185bac51305a1576fc7e" + ), + ("0.7.20", "unknown-linux-gnu", "aarch64"): ( + "675165f879d6833aa313ecb25ac44781e131933a984727e180b3218d2cd6c1e9" + ), + ("0.7.20", "unknown-linux-gnu", "x86_64"): ( + "10f204426ff188925d22a53c1d0310d190a8d4d24513712e1b8e2ca9873f0666" + ), + } + version = str(self.spec.version) + arch = translate_arch(self.spec.target) + platform = translate_platform(self.spec.platform) + key = (version, platform, arch) + + if key not in checksums: + msg = f"Unsupported platform/arch for version {version}: {platform}-{arch}." + raise InstallError(msg) + + self.fetcher.digest = checksums[key] + super().do_stage(mirror_only) + + def install(self, spec, prefix): + mkdir(prefix.bin) + install("uv", prefix.bin.uv) + install("uvx", prefix.bin.uvx) diff --git a/recipes/icon-dsl/25.8/gh200/compilers.yaml b/recipes/icon-dsl/25.8/gh200/compilers.yaml new file mode 100644 index 0000000..f456b5a --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/compilers.yaml @@ -0,0 +1,9 @@ +bootstrap: + spec: gcc@12.3 +gcc: + specs: + - gcc@13 +llvm: + requires: gcc@13 + specs: + - nvhpc@25.1 diff --git a/recipes/icon-dsl/25.8/gh200/config.yaml b/recipes/icon-dsl/25.8/gh200/config.yaml new file mode 100644 index 0000000..ac4ba9c --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/config.yaml @@ -0,0 +1,7 @@ +name: icon-dsl +store: /user-environment +spack: + repo: https://github.com/spack/spack.git + commit: releases/v0.23 +modules: false +description: Build and runtime dependencies for ICON-DSL diff --git a/recipes/icon-dsl/25.8/gh200/environments.yaml b/recipes/icon-dsl/25.8/gh200/environments.yaml new file mode 100644 index 0000000..7fde2c8 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/environments.yaml @@ -0,0 +1,47 @@ +myenv: + compiler: + - toolchain: gcc + spec: gcc + - toolchain: llvm + spec: nvhpc + mpi: + spec: cray-mpich@8.1.30%nvhpc + gpu: cuda + specs: + # icon4py deps + - python@3.11 + - py-cupy +cuda cuda_arch=90 + - ghex +python +cuda cuda_arch=90 + - py-mpi4py + - icon4py@icon_20250328 + # icon deps + - boost + - cuda@12 + - eccodes@2.36.4%nvhpc +tools +fortran +aec +openmp jp2k=jasper + - cosmo-eccodes-definitions@2.36.0.3 + - hdf5%nvhpc +szip +hl +fortran +mpi + - netcdf-c@4.9.2%nvhpc + - netcdf-cxx4@4.3.1%nvhpc + - netcdf-fortran@4.6.1%nvhpc + - osu-micro-benchmarks@5.9%nvhpc + - openblas + # for validation + - cdo + # everything needed for nccl on SS11 + - nccl + - nccl-tests + # extras + - libfyaml + - zlib-ng + - cmake + unify: true + variants: + - +mpi + - +cuda + - cuda_arch=90 + views: + default: + link: roots + uenv: + prefix_paths: + LD_LIBRARY_PATH: [lib, lib64] diff --git a/recipes/icon-dsl/25.8/gh200/extra/reframe.yaml b/recipes/icon-dsl/25.8/gh200/extra/reframe.yaml new file mode 100644 index 0000000..363f809 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/extra/reframe.yaml @@ -0,0 +1,6 @@ +default: + features: [osu-micro-benchmarks, mpi, serial, openmp] + cc: mpicc + cxx: mpic++ + ftn: mpifort + activation: /user-environment/env/default/activate.sh diff --git a/recipes/icon-dsl/25.8/gh200/modules.yaml b/recipes/icon-dsl/25.8/gh200/modules.yaml new file mode 100644 index 0000000..a4010ae --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/modules.yaml @@ -0,0 +1,26 @@ +modules: + # Paths to check when creating modules for all module sets + prefix_inspections: + bin: + - PATH + lib: + - LD_LIBRARY_PATH + lib64: + - LD_LIBRARY_PATH + + default: + arch_folder: false + # Where to install modules + roots: + tcl: /snap/modules + tcl: + all: + autoload: run + hash_length: 0 + hide_implicits: true + exclude: + - '%gcc@7.5.0' + - '%gcc@12' + - 'gcc %gcc@7.5.0' + projections: + all: '{name}/{version}' diff --git a/recipes/icon-dsl/25.8/gh200/pre-install b/recipes/icon-dsl/25.8/gh200/pre-install new file mode 100644 index 0000000..ba88283 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/pre-install @@ -0,0 +1,12 @@ +#!/bin/bash + +packages=("cosmo-eccodes-definitions") +SPACK_C2SM_TAG="v0.22.2.1" + +git clone -b ${SPACK_C2SM_TAG} https://github.com/C2SM/spack-c2sm.git + +for package in "${packages[@]}"; do + cp -r spack-c2sm/repos/c2sm/packages/"${package}" store/repo/packages +done + +rm -rf spack-c2sm diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/cmake_install_rpath.patch b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/cmake_install_rpath.patch new file mode 100644 index 0000000..7e2b250 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/cmake_install_rpath.patch @@ -0,0 +1,11 @@ +--- a/cmake/ecbuild_append_to_rpath.cmake ++++ b/cmake/ecbuild_append_to_rpath.cmake +@@ -31,7 +31,7 @@ function( _path_append var path ) + else() + list( FIND ${var} ${path} _found ) + if( _found EQUAL "-1" ) +- set( ${var} "${${var}}:${path}" PARENT_SCOPE ) ++ set( ${var} "${${var}};${path}" PARENT_SCOPE ) + endif() + endif() + endfunction() diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/openjpeg_jasper.patch b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/openjpeg_jasper.patch new file mode 100644 index 0000000..5793f56 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/openjpeg_jasper.patch @@ -0,0 +1,39 @@ +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -43,6 +43,18 @@ ecbuild_add_option( FEATURE JPG + DESCRIPTION "support for JPG decoding/encoding" + DEFAULT ON + ) ++# Options related to JPG. The Jasper and OpenJPEG libraries ++ecbuild_add_option( FEATURE JPG_LIBJASPER ++ DESCRIPTION "Support for JPG decoding/encoding with the Jasper library" ++ CONDITION ENABLE_JPG ++ DEFAULT ON ++) ++ecbuild_add_option( FEATURE JPG_LIBOPENJPEG ++ DESCRIPTION "Support for JPG decoding/encoding with the OpenJPEG library" ++ CONDITION ENABLE_JPG ++ DEFAULT ON ++) ++ + + ecbuild_add_option( FEATURE PNG + DESCRIPTION "support for PNG decoding/encoding" +@@ -144,7 +156,7 @@ if( ENABLE_JPG ) + + find_package( OpenJPEG ) + +- if( JASPER_FOUND ) ++ if( JASPER_FOUND AND ENABLE_JPG_LIBJASPER ) + list( APPEND ECCODES_TPLS Jasper ) + set( HAVE_JPEG 1 ) + set( HAVE_LIBJASPER 1 ) +@@ -152,7 +164,7 @@ if( ENABLE_JPG ) + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" JASPER_VERSION_MAJOR "${JASPER_VERSION_STRING}") + endif() + +- if( OPENJPEG_FOUND ) ++ if( OPENJPEG_FOUND AND ENABLE_JPG_LIBOPENJPEG ) + list( APPEND ECCODES_TPLS OpenJPEG ) + set( HAVE_JPEG 1 ) + set( HAVE_LIBOPENJPEG 1 ) diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/package.py new file mode 100644 index 0000000..aeb4692 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/package.py @@ -0,0 +1,385 @@ +# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other +# Spack Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + + +from spack.package import * + +_definitions = { + # German Meteorological Service (Deutscher Wetterdienst, DWD): + "edzw": { + "conflicts": {"when": "@:2.19.1,2.22.0,2.24.0:"}, + "resources": [ + { + "when": "@2.20.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.20.0-1.tar.gz", + "sha256": "a92932f8a13c33cba65d3a33aa06c7fb4a37ed12a78e9abe2c5e966402b99af4", + }, + { + "when": "@2.21.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.21.0-3.tar.bz2", + "sha256": "046f1f6450abb3b44c31dee6229f4aab06ca0d3576e27e93e05ccb7cd6e2d9d9", + }, + { + "when": "@2.22.1", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.22.1-1.tar.bz2", + "sha256": "be73102a0dcabb236bacd2a70c7b5475f673fda91b49e34df61bef0fa5ad3389", + }, + { + "when": "@2.23.0", + "url": "http://opendata.dwd.de/weather/lib/grib/eccodes_definitions.edzw-2.23.0-4.tar.bz2", + "sha256": "c5db32861c7d23410aed466ffef3ca661410d252870a3949442d3ecb176aa338", + }, + ], + } +} + + +class Eccodes(CMakePackage): + """ecCodes is a package developed by ECMWF for processing meteorological + data in GRIB (1/2), BUFR (3/4) and GTS header formats.""" + + homepage = "https://software.ecmwf.int/wiki/display/ECC/ecCodes+Home" + url = "https://confluence.ecmwf.int/download/attachments/45757960/eccodes-2.2.0-Source.tar.gz?api=v2" + git = "https://github.com/ecmwf/eccodes.git" + list_url = "https://confluence.ecmwf.int/display/ECC/Releases" + + maintainers("skosukhin", "victoria-cherkas", "dominichofer", "climbfuji") + + license("Apache-2.0") + + version("develop", branch="develop") + version("2.36.4", + sha256="198ccb26e8df96544c668ea6853ea153535ab78b10c43339a678f271337aa0da", + url="https://github.com/ecmwf/eccodes/archive/refs/tags/2.36.4.tar.gz" + ) + version("2.34.0", sha256="3cd208c8ddad132789662cf8f67a9405514bfefcacac403c0d8c84507f303aba") + version("2.33.0", sha256="bdcec8ce63654ec6803400c507f01220a9aa403a45fa6b5bdff7fdcc44fd7daf") + version("2.32.1", sha256="ad2ac1bf36577b1d35c4a771b4d174a06f522a1e5ef6c1f5e53a795fb624863e") + version("2.32.0", sha256="b57e8eeb0eba0c05d66fda5527c4ffa84b5ab35c46bcbc9a2227142973ccb8e6") + version("2.31.0", sha256="808ecd2c11fbf2c3f9fc7a36f8c2965b343f3151011b58a1d6e7cc2e6b3cac5d") + version("2.25.0", sha256="8975131aac54d406e5457706fd4e6ba46a8cc9c7dd817a41f2aa64ce1193c04e") + version("2.24.2", sha256="c60ad0fd89e11918ace0d84c01489f21222b11d6cad3ff7495856a0add610403") + version("2.23.0", sha256="cbdc8532537e9682f1a93ddb03440416b66906a4cc25dec3cbd73940d194bf0c") + version("2.22.1", sha256="75c7ee96469bb30b0c8f7edbdc4429ece4415897969f75c36173545242bc9e85") + version("2.21.0", sha256="da0a0bf184bb436052e3eae582defafecdb7c08cdaab7216780476e49b509755") + version("2.20.0", sha256="207a3d7966e75d85920569b55a19824673e8cd0b50db4c4dac2d3d52eacd7985") + version("2.19.1", sha256="9964bed5058e873d514bd4920951122a95963128b12f55aa199d9afbafdd5d4b") + version("2.18.0", sha256="d88943df0f246843a1a062796edbf709ef911de7269648eef864be259e9704e3") + version("2.13.0", sha256="c5ce1183b5257929fc1f1c8496239e52650707cfab24f4e0e1f1a471135b8272") + version("2.5.0", sha256="18ab44bc444168fd324d07f7dea94f89e056f5c5cd973e818c8783f952702e4e") + version("2.2.0", sha256="1a4112196497b8421480e2a0a1164071221e467853486577c4f07627a702f4c3") + + # we are still using spack v0.21 v0.22, so comment these out for now + #depends_on("c", type="build") # generated + #depends_on("cxx", type="build") # generated + #depends_on("fortran", type="build") # generated + + variant("tools", default=False, description="Build the command line tools") + variant("netcdf", default=False, description="Enable GRIB to NetCDF conversion tool") + variant( + "jp2k", + default="openjpeg", + values=("openjpeg", "jasper", "none"), + description="Specify JPEG2000 decoding/encoding backend", + ) + variant("png", default=False, description="Enable PNG support for decoding/encoding") + variant( + "aec", default=True, description="Enable Adaptive Entropy Coding for decoding/encoding" + ) + variant("pthreads", default=False, description="Enable POSIX threads") + variant("openmp", default=False, description="Enable OpenMP threads") + variant( + "memfs", default=False, description="Enable memory based access to definitions/samples" + ) + variant("fortran", default=False, description="Enable the Fortran support") + variant("shared", default=True, description="Build shared versions of the libraries") + + variant( + "extra_definitions", + values=any_combination_of(*_definitions.keys()), + description="List of extra definitions to install", + ) + + depends_on("netcdf-c", when="+netcdf") + # Cannot be built with openjpeg@2.0.x. + depends_on("openjpeg@1.5.0:1.5,2.1.0:2.3", when="jp2k=openjpeg") + # Additional constraint for older versions. + depends_on("openjpeg@:2.1", when="@:2.16 jp2k=openjpeg") + + with when("jp2k=jasper"): + depends_on("jasper") + # jasper 3.x compat from commit 86f0b35f1a8492cb16f82fb976a0a5acd2986ac2 + depends_on("jasper@:2", when="@:2.25.0") + + depends_on("libpng", when="+png") + depends_on("libaec", when="+aec") + # Can be built with Python 2 or Python 3. + depends_on("python", when="+memfs", type="build") + + depends_on("cmake@3.6:", type="build") + depends_on("cmake@3.12:", when="@2.19:", type="build") + + # TODO: ecbuild was only used for the @develop branch + # however, testing 2.36.4, it appears to be a requirement. + # this might be because they package the software differently in GitHub + # (they normally provide releases as tar balls on Confluence) + depends_on("ecbuild", type="build") + #depends_on("ecbuild", type="build", when="@develop") + + conflicts("+openmp", when="+pthreads", msg="Cannot enable both POSIX threads and OMP") + + conflicts( + "+netcdf", + when="~tools", + msg="Cannot enable the NetCDF conversion tool " "when the command line tools are disabled", + ) + + conflicts( + "~tools", + when="@:2.18.0", + msg="The command line tools can be disabled " "only starting version 2.19.0", + ) + + for center, definitions in _definitions.items(): + kwargs = definitions.get("conflicts", None) + if kwargs: + conflicts("extra_definitions={0}".format(center), **kwargs) + for kwargs in definitions.get("resources", []): + resource( + name=center, + destination="spack-definitions", + placement="definitions.{0}".format(center), + **kwargs, + ) + + # Enforce linking against the specified JPEG2000 backend, see also + # https://github.com/ecmwf/eccodes/commit/2c10828495900ff3d80d1e570fe96c1df16d97fb + patch("openjpeg_jasper.patch", when="@:2.16") + + # CMAKE_INSTALL_RPATH must be a semicolon-separated list. + patch("cmake_install_rpath.patch", when="@:2.10") + + # Fix a bug preventing cmake from finding NetCDF: + patch( + "https://github.com/ecmwf/ecbuild/commit/3916c7d22575c45166fcc89edcbe02a6e9b81aa2.patch?full_index=1", + sha256="9dcc4affaaa850d4b7247baa939d0f9ffedea132369f1afc3f248dbf720386c9", + when="@:2.4.0+netcdf", + ) + + @when("%nag+fortran") + def patch(self): + # A number of Fortran source files assume that the kinds of integer and + # real variables are specified in bytes. However, the NAG compiler + # accepts such code only with an additional compiler flag -kind=byte. + # We do not simply add the flag because all user applications would + # have to be compiled with this flag too, which goes against one of the + # purposes of using the NAG compiler: make sure the code does not + # contradict the Fortran standards. The following logic could have been + # implemented as regular patch files, which would, however, be quite + # large. We would also have to introduce several versions of each patch + # file to support different versions of the package. + + patch_kind_files = [ + "fortran/eccodes_f90_head.f90", + "fortran/eccodes_f90_tail.f90", + "fortran/grib_f90_head.f90", + "fortran/grib_f90_tail.f90", + "fortran/grib_types.f90", + ] + + patch_unix_ext_files = [] + + if self.run_tests: + patch_kind_files.extend( + [ + "examples/F90/grib_print_data.f90", + "examples/F90/grib_print_data_static.f90", + # Files that need patching only when the extended regression + # tests are enabled, which we disable unconditionally: + # 'examples/F90/bufr_attributes.f90', + # 'examples/F90/bufr_expanded.f90', + # 'examples/F90/bufr_get_keys.f90', + # 'examples/F90/bufr_read_scatterometer.f90', + # 'examples/F90/bufr_read_synop.f90', + # 'examples/F90/bufr_read_temp.f90', + # 'examples/F90/bufr_read_tempf.f90', + # 'examples/F90/bufr_read_tropical_cyclone.f90', + # 'examples/F90/grib_clone.f90', + # 'examples/F90/grib_get_data.f90', + # 'examples/F90/grib_nearest.f90', + # 'examples/F90/grib_precision.f90', + # 'examples/F90/grib_read_from_file.f90', + # 'examples/F90/grib_samples.f90', + # 'examples/F90/grib_set_keys.f90' + ] + ) + + patch_unix_ext_files.extend( + [ + "examples/F90/bufr_ecc-1284.f90", + "examples/F90/grib_set_data.f90", + "examples/F90/grib_set_packing.f90", + # Files that need patching only when the extended regression + # tests are enabled, which we disable unconditionally: + # 'examples/F90/bufr_copy_data.f90', + # 'examples/F90/bufr_get_string_array.f90', + # 'examples/F90/bufr_keys_iterator.f90', + # 'examples/F90/get_product_kind.f90', + # 'examples/F90/grib_count_messages_multi.f90' + ] + ) + + kwargs = {"string": False, "backup": False, "ignore_absent": True} + + # Return the kind and not the size: + filter_file( + r"(^\s*kind_of_double\s*=\s*)(\d{1,2})(\s*$)", + "\\1kind(real\\2)\\3", + "fortran/grib_types.f90", + **kwargs, + ) + filter_file( + r"(^\s*kind_of_\w+\s*=\s*)(\d{1,2})(\s*$)", + "\\1kind(x\\2)\\3", + "fortran/grib_types.f90", + **kwargs, + ) + + # Replace integer kinds: + for size, r in [(2, 4), (4, 9), (8, 18)]: + filter_file( + r"(^\s*integer\((?:kind=)?){0}(\).*)".format(size), + "\\1selected_int_kind({0})\\2".format(r), + *patch_kind_files, + **kwargs, + ) + + # Replace real kinds: + for size, p, r in [(4, 6, 37), (8, 15, 307)]: + filter_file( + r"(^\s*real\((?:kind=)?){0}(\).*)".format(size), + "\\1selected_real_kind({0}, {1})\\2".format(p, r), + *patch_kind_files, + **kwargs, + ) + + # Enable getarg and exit subroutines: + filter_file( + r"(^\s*program\s+\w+)(\s*$)", + "\\1; use f90_unix_env; use f90_unix_proc\\2", + *patch_unix_ext_files, + **kwargs, + ) + + @property + def libs(self): + libraries = [] + + query_parameters = self.spec.last_query.extra_parameters + + if "shared" in query_parameters: + shared = True + elif "static" in query_parameters: + shared = False + else: + shared = "+shared" in self.spec + + # Return Fortran library if requested: + return_fortran = "fortran" in query_parameters + # Return C library if either requested or the Fortran library is not + # requested (to avoid overlinking) or the static libraries are + # requested: + return_c = "c" in query_parameters or not (return_fortran and shared) + # Return MEMFS library only if enabled and the static libraries are + # requested: + return_memfs = "+memfs" in self.spec and not shared + + if return_fortran: + libraries.append("libeccodes_f90") + + if return_c: + libraries.append("libeccodes") + + if return_memfs: + libraries.append("libeccodes_memfs") + + libs = find_libraries(libraries, root=self.prefix, shared=shared, recursive=True) + + if libs and len(libs) == len(libraries): + return libs + + msg = "Unable to recursively locate {0} {1} libraries in {2}" + raise spack.error.NoLibrariesError( + msg.format("shared" if shared else "static", self.spec.name, self.spec.prefix) + ) + + @run_before("cmake") + def check_fortran(self): + if "+fortran" in self.spec and self.compiler.fc is None: + raise InstallError("Fortran interface requires a Fortran compiler!") + + def cmake_args(self): + jp2k = self.spec.variants["jp2k"].value + + args = [ + self.define_from_variant("ENABLE_BUILD_TOOLS", "tools"), + self.define_from_variant("ENABLE_NETCDF", "netcdf"), + self.define("ENABLE_JPG", jp2k != "none"), + self.define("ENABLE_JPG_LIBJASPER", jp2k == "jasper"), + self.define("ENABLE_JPG_LIBOPENJPEG", jp2k == "openjpeg"), + self.define_from_variant("ENABLE_PNG", "png"), + self.define_from_variant("ENABLE_AEC", "aec"), + self.define_from_variant("ENABLE_ECCODES_THREADS", "pthreads"), + self.define_from_variant("ENABLE_ECCODES_OMP_THREADS", "openmp"), + self.define_from_variant("ENABLE_MEMFS", "memfs"), + self.define( + "ENABLE_PYTHON{0}".format("2" if self.spec.satisfies("@2.20.0:") else ""), False + ), + self.define_from_variant("ENABLE_FORTRAN", "fortran"), + self.define("BUILD_SHARED_LIBS", "BOTH" if "+shared" in self.spec else "OFF"), + self.define("ENABLE_TESTS", self.run_tests), + # Examples are not installed and are just part of the test suite: + self.define("ENABLE_EXAMPLES", self.run_tests), + # Unconditionally disable the extended regression tests, since they + # download additional data (~134MB): + self.define("ENABLE_EXTRA_TESTS", False), + ] + + if self.spec.satisfies("+netcdf"): + # Prevent possible overriding by environment variables NETCDF_ROOT, NETCDF_DIR, and + # NETCDF_PATH: + args.append(self.define("NETCDF_PATH", self.spec["netcdf-c"].prefix)) + # Prevent overriding by environment variable HDF5_ROOT (starting version 2.14.0, + # ecCodes is shipped with ecBuild 3.1.0+, which does not seem to rely on the HDF5_ROOT + # variable): + if self.spec.satisfies("@:2.13"): + args.append(self.define("HDF5_ROOT", self.spec["hdf5"].prefix)) + + if jp2k == "openjpeg": + args.append(self.define("OPENJPEG_PATH", self.spec["openjpeg"].prefix)) + + if self.spec.satisfies("+png"): + args.append(self.define("ZLIB_ROOT", self.spec["zlib-api"].prefix)) + + if self.spec.satisfies("+aec"): + # Prevent overriding by environment variables AEC_DIR and AEC_PATH: + args.append(self.define("AEC_DIR", self.spec["libaec"].prefix)) + + return args + + @run_after("install") + def install_extra_definitions(self): + for center in self.spec.variants["extra_definitions"].value: + if center != "none": + center_dir = "definitions.{0}".format(center) + install_tree( + join_path(self.stage.source_path, "spack-definitions", center_dir), + join_path(self.prefix.share.eccodes, center_dir), + ) + + def check(self): + # https://confluence.ecmwf.int/display/ECC/ecCodes+installation + with working_dir(self.build_directory): + ctest() diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/readme.md b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/readme.md new file mode 100644 index 0000000..9678342 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/eccodes/readme.md @@ -0,0 +1 @@ +copied from mainline spack November 5 2024 so that we can add eccodes 2.36.0 for mch production diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/ghex/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/ghex/package.py new file mode 100644 index 0000000..8f50e28 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/ghex/package.py @@ -0,0 +1,93 @@ +from spack.package import * + + +class Ghex(CMakePackage, CudaPackage, ROCmPackage): + """GHEX is a generic halo-exchange library.""" + + homepage = "https://github.com/ghex-org/GHEX" + url = "https://github.com/ghex-org/GHEX/archive/refs/tags/v0.3.0.tar.gz" + git = "https://github.com/ghex-org/GHEX.git" + maintainers = ["boeschf"] + + version("0.4.1", tag="v0.4.1", submodules=True) + version("0.4.0", tag="v0.4.0", submodules=True) + version("0.3.0", tag="v0.3.0", submodules=True) + version("master", branch="master", submodules=True) + + depends_on("cxx", type="build") + + generator("ninja") + + backends = ("mpi", "ucx", "libfabric") + variant( + "backend", + default="mpi", + description="Transport backend", + values=backends, + multi=False, + ) + variant("xpmem", default=False, description="Use xpmem shared memory") + variant("python", default=True, description="Build Python bindings") + + depends_on("cmake@3.21:", type="build") + depends_on("mpi") + depends_on("boost") + depends_on("xpmem", when="+xpmem", type=("build", "run")) + + depends_on("oomph") + for backend in backends: + depends_on(f"oomph backend={backend}", when=f"backend={backend}") + depends_on("oomph+cuda", when="+cuda") + depends_on("oomph+rocm", when="+rocm") + depends_on("oomph@0.3:", when="@0.3:") + + conflicts("+cuda+rocm") + + with when("+python"): + extends("python") + depends_on("python@3.7:", type="build") + depends_on("py-pip", type="build") + depends_on("py-pybind11", type="build") + depends_on("py-mpi4py", type=("build", "run")) + depends_on("py-numpy", type=("build", "run")) + + depends_on("py-pytest", when="+python", type=("test")) + + def cmake_args(self): + spec = self.spec + + args = [ + self.define("GHEX_USE_BUNDLED_LIBS", True), + self.define("GHEX_USE_BUNDLED_GRIDTOOLS", True), + self.define("GHEX_USE_BUNDLED_GTEST", self.run_tests), + self.define("GHEX_USE_BUNDLED_OOMPH", False), + self.define( + "GHEX_TRANSPORT_BACKEND", spec.variants["backend"].value.upper() + ), + self.define_from_variant("GHEX_USE_XPMEM", "xpmem"), + self.define_from_variant("GHEX_BUILD_PYTHON_BINDINGS", "python"), + self.define("GHEX_WITH_TESTING", self.run_tests), + ] + + if spec.satisfies("+python"): + args.append(self.define("GHEX_PYTHON_LIB_PATH", python_platlib)) + + if self.run_tests and spec.satisfies("^openmpi"): + args.append(self.define("MPIEXEC_PREFLAGS", "--oversubscribe")) + + if "+cuda" in spec and spec.variants["cuda_arch"].value != "none": + arch_str = ";".join(spec.variants["cuda_arch"].value) + args.append(self.define("CMAKE_CUDA_ARCHITECTURES", arch_str)) + args.append(self.define("GHEX_USE_GPU", True)) + args.append(self.define("GHEX_GPU_TYPE", "NVIDIA")) + + if "+rocm" in spec and spec.variants["amdgpu_target"].value != "none": + arch_str = ";".join(spec.variants["amdgpu_target"].value) + args.append(self.define("CMAKE_HIP_ARCHITECTURES", arch_str)) + args.append(self.define("GHEX_USE_GPU", True)) + args.append(self.define("GHEX_GPU_TYPE", "AMD")) + + if spec.satisfies("~cuda~rocm"): + args.append(self.define("GHEX_USE_GPU", False)) + + return args diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/cmake_install_path.patch b/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/cmake_install_path.patch new file mode 100644 index 0000000..fa6fde1 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/cmake_install_path.patch @@ -0,0 +1,27 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index d5420e0..35dbe56 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -105,11 +105,11 @@ install(FILES ${PROJECT_BINARY_DIR}/include/hwmalloc/config.hpp + install(EXPORT HWMALLOC-targets + FILE HWMALLOC-targets.cmake + NAMESPACE HWMALLOC:: +- DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/HWMALLOCConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/HWMALLOCConfig.cmake +- INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + write_basic_package_version_file(HWMALLOCConfigVersion.cmake + VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +@@ -120,7 +120,7 @@ install( + ${CMAKE_CURRENT_BINARY_DIR}/HWMALLOCConfigVersion.cmake + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindNUMA.cmake + DESTINATION +- ${CMAKE_INSTALL_LIBDIR}/cmake) ++ ${CMAKE_INSTALL_LIBDIR}/hwmalloc/cmake) + + export(EXPORT HWMALLOC-targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/HWMALLOC-targets.cmake") diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/package.py new file mode 100644 index 0000000..c656dc1 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/hwmalloc/package.py @@ -0,0 +1,52 @@ +from spack.package import * + + +class Hwmalloc(CMakePackage, CudaPackage, ROCmPackage): + """HWMALLOC is a allocator which supports memory registration for e.g. remote memory access""" + + homepage = "https://github.com/ghex-org/hwmalloc" + url = "https://github.com/ghex-org/hwmalloc/archive/refs/tags/v0.3.0.tar.gz" + git = "https://github.com/ghex-org/hwmalloc.git" + maintainers = ["boeschf"] + + version("0.3.0", sha256="d4d4ac6087a806600d79fb62c02719ca3d58a412968fe1ef4a2fd58d9e7ee950") + version("0.2.0", sha256="734758a390a3258b86307e4aef50a7ca2e5d0e2e579f18aeefcd05397e114419") + version("0.1.0", sha256="06e9bfcef0ecce4d19531ccbe03592b502d1281c7a092bc0ff51ca187899b21c") + version("master", branch="master") + + depends_on("cxx", type="build") + + generator("ninja") + + depends_on("numactl", type=("build", "run")) + depends_on("boost", type=("build")) + depends_on("cmake@3.19:", type="build") + + variant( + "numa-throws", + default=False, + description="True if numa_tools may throw during initialization", + ) + variant("numa-local", default=True, description="Use numa_tools for local node allocations") + variant("logging", default=False, description="print logging info to cerr") + + patch("cmake_install_path.patch", when="@:0.3.0", level=1) + + def cmake_args(self): + args = [ + self.define_from_variant("HWMALLOC_NUMA_THROWS", "numa-throws"), + self.define_from_variant("HWMALLOC_NUMA_FOR_LOCAL", "numa-local"), + self.define_from_variant("HWMALLOC_ENABLE_LOGGING", "logging"), + self.define("HWMALLOC_WITH_TESTING", self.run_tests), + ] + + if "+cuda" in self.spec: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", True)) + args.append(self.define("HWMALLOC_DEVICE_RUNTIME", "cuda")) + elif "+rocm" in self.spec: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", True)) + args.append(self.define("HWMALLOC_DEVICE_RUNTIME", "hip")) + else: + args.append(self.define("HWMALLOC_ENABLE_DEVICE", False)) + + return args diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/icon4py/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/icon4py/package.py new file mode 100644 index 0000000..9ee413e --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/icon4py/package.py @@ -0,0 +1,109 @@ +import json +import os +import pathlib + +import llnl +from llnl.util import tty +from spack import * + + +class Icon4py(Package): + extends("python") + depends_on("python@3.11:") + + depends_on("git") + depends_on("boost@1.85:+mpi+python", type=("build", "run")) + depends_on("uv@0.7:", type="build") + depends_on("bzip2", type="build") + depends_on("py-numpy") + depends_on("py-cffi") + depends_on("py-pybind11") + depends_on("py-nanobind") + depends_on("py-mpi4py") + depends_on("py-cupy +cuda") + depends_on("ghex +python +cuda") + + version( + "icon_20250328", + sha256="8573ef031d207438f549511e859f522c60163ea660aafea93ef4991b9010739a", + extension="zip", + ) + + def url_for_version(self, version): + return f"https://github.com/c2sm/icon4py/archive/refs/heads/{version}.zip" + + def install(self, spec, prefix): + uv = prepare_uv() + python_spec = spec["python"] + venv_path = prefix.share.venv + + tty.msg(f"creating venv using spack python at: {python_spec.command.path}") + uv( + "venv", + "--seed", + "--relocatable", + "--system-site-packages", + str(venv_path), + "--python", + python_spec.command.path, + ) + + tty.msg(f"grabbing spack installed packages (distributions)") + pip = Executable(venv_path.bin.pip) + spack_installed = get_installed_pkg(pip) + + tty.msg(f"installing missing packages") + uv( + "sync", + "--active", + "--extra", + "all", + "--extra", + "cuda12", + "--inexact", + "--no-editable", + "--python", + str(venv_path.bin.python), + *no_install_options([*spack_installed, "cupy-cuda12x", "ghex"]), + extra_env={"VIRTUAL_ENV": str(venv_path)}, + ) + + tty.msg(f"linking spack installed packages into venv") + pathlib.Path( + f"{venv_path.lib.python}{python_spec.version.up_to(2)}/site-packages/spack_installed.pth" + ).write_text(pythonpath_to_pth()) + + tty.msg(f"running py2fgen") + py2fgen = Executable(venv_path.bin.py2fgen) + py2fgen( + "icon4py.tools.py2fgen.wrappers.all_bindings", + "diffusion_init,diffusion_run,grid_init,solve_nh_init,solve_nh_run", + "icon4py_bindings", + "-o", + prefix.src, + extra_env={"VIRTUAL_ENV": str(venv_path)}, + ) + + +def prepare_uv(): + uv = which("uv") + uv.add_default_env("UV_NO_CACHE", "true") + uv.add_default_env("UV_NO_MANAGED_PYTHON", "true") + uv.add_default_env("UV_PYTHON_DOWNLOADS", "never") + return uv + + +def get_installed_pkg(pip): + return [ + item["name"] for item in json.loads(pip("list", "--format", "json", output=str)) + ] + + +def no_install_options(installed): + for name in installed: + yield "--no-install-package" + yield name + + +def pythonpath_to_pth(): + return "\n".join(os.environ["PYTHONPATH"].split(":")) diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.2.patch b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.2.patch new file mode 100644 index 0000000..5dc7e2e --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.2.patch @@ -0,0 +1,102 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index ba19089..2ba222a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,12 @@ + cmake_minimum_required(VERSION 3.17) + # CMake version is set at 3.17 because of find_package(CUDAToolkit) + ++if (NOT ${CMAKE_VERSION} VERSION_LESS 3.27) ++ # new in 3.27: additionally use uppercase _ROOT ++ # environment and CMake variables for find_package ++ cmake_policy(SET CMP0144 NEW) ++endif() ++ + set(OOMPH_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + list(APPEND CMAKE_MODULE_PATH "${OOMPH_MODULE_PATH}") + +@@ -108,11 +114,11 @@ endif() + install(EXPORT oomph-targets + FILE oomph-targets.cmake + NAMESPACE oomph:: +- DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ DESTINATION ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/oomphConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/oomphConfig.cmake +- INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) ++ INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + write_basic_package_version_file(oomphConfigVersion.cmake + VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) +@@ -125,7 +131,7 @@ install( + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindUCX.cmake + ${CMAKE_CURRENT_LIST_DIR}/cmake/FindPMIx.cmake + DESTINATION +- ${CMAKE_INSTALL_LIBDIR}/cmake) ++ ${CMAKE_INSTALL_LIBDIR}/oomph/cmake) + + export(EXPORT oomph-targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/oomph-targets.cmake") +diff --git a/cmake/oomph_external_dependencies.cmake b/cmake/oomph_external_dependencies.cmake +index ec672b5..a578ef5 100644 +--- a/cmake/oomph_external_dependencies.cmake ++++ b/cmake/oomph_external_dependencies.cmake +@@ -31,17 +31,30 @@ endif() + # --------------------------------------------------------------------- + # google test setup + # --------------------------------------------------------------------- +-add_external_cmake_project( +- NAME googletest +- PATH ext/googletest +- INTERFACE_NAME ext-gtest +- LIBS libgtest.a libgtest_main.a +- CMAKE_ARGS +- "-DCMAKE_BUILD_TYPE=release" +- "-DBUILD_SHARED_LIBS=OFF" +- "-DBUILD_GMOCK=OFF") +-# on some systems we need link explicitly against threads +-if (TARGET ext-gtest) +- find_package (Threads) +- target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++cmake_dependent_option(OOMPH_USE_BUNDLED_GTEST "Use bundled googletest lib." ON ++ "OOMPH_USE_BUNDLED_LIBS" OFF) ++if (OOMPH_WITH_TESTING) ++ if(OOMPH_USE_BUNDLED_GTEST) ++ add_external_cmake_project( ++ NAME googletest ++ PATH ext/googletest ++ INTERFACE_NAME ext-gtest ++ LIBS libgtest.a libgtest_main.a ++ CMAKE_ARGS ++ "-DCMAKE_BUILD_TYPE=release" ++ "-DBUILD_SHARED_LIBS=OFF" ++ "-DBUILD_GMOCK=OFF") ++ # on some systems we need link explicitly against threads ++ if (TARGET ext-gtest) ++ find_package (Threads) ++ target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++ endif() ++ else() ++ # Use system provided google test ++ find_package(GTest REQUIRED) ++ add_library(ext-gtest INTERFACE) ++ if (${CMAKE_VERSION} VERSION_LESS "3.20.0") ++ target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++ else() ++ target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ endif() ++ endif() + endif() +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index 06d703a..5217bba 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -65,6 +65,7 @@ function(reg_parallel_test t_ lib n) + NAME ${t} + COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${n} ${MPIEXEC_PREFLAGS} + $ ${MPIEXEC_POSTFLAGS}) ++ set_tests_properties(${t} PROPERTIES RUN_SERIAL TRUE) + endfunction() + + if (OOMPH_WITH_MPI) diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.3.patch b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.3.patch new file mode 100644 index 0000000..aac73e8 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/install_0.3.patch @@ -0,0 +1,57 @@ +diff --git a/cmake/oomph_external_dependencies.cmake b/cmake/oomph_external_dependencies.cmake +index a578ef5..92de39b 100644 +--- a/cmake/oomph_external_dependencies.cmake ++++ b/cmake/oomph_external_dependencies.cmake +@@ -33,28 +33,30 @@ endif() + # --------------------------------------------------------------------- + cmake_dependent_option(OOMPH_USE_BUNDLED_GTEST "Use bundled googletest lib." ON + "OOMPH_USE_BUNDLED_LIBS" OFF) +-if(OOMPH_USE_BUNDLED_GTEST) +- add_external_cmake_project( +- NAME googletest +- PATH ext/googletest +- INTERFACE_NAME ext-gtest +- LIBS libgtest.a libgtest_main.a +- CMAKE_ARGS +- "-DCMAKE_BUILD_TYPE=release" +- "-DBUILD_SHARED_LIBS=OFF" +- "-DBUILD_GMOCK=OFF") +- # on some systems we need link explicitly against threads +- if (TARGET ext-gtest) +- find_package (Threads) +- target_link_libraries(ext-gtest INTERFACE Threads::Threads) +- endif() +-else() +- # Use system provided google test +- find_package(GTest REQUIRED) +- add_library(ext-gtest INTERFACE) +- if (${CMAKE_VERSION} VERSION_LESS "3.20.0") +- target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++if (OOMPH_WITH_TESTING) ++ if(OOMPH_USE_BUNDLED_GTEST) ++ add_external_cmake_project( ++ NAME googletest ++ PATH ext/googletest ++ INTERFACE_NAME ext-gtest ++ LIBS libgtest.a libgtest_main.a ++ CMAKE_ARGS ++ "-DCMAKE_BUILD_TYPE=release" ++ "-DBUILD_SHARED_LIBS=OFF" ++ "-DBUILD_GMOCK=OFF") ++ # on some systems we need link explicitly against threads ++ if (TARGET ext-gtest) ++ find_package (Threads) ++ target_link_libraries(ext-gtest INTERFACE Threads::Threads) ++ endif() + else() +- target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ # Use system provided google test ++ find_package(GTest REQUIRED) ++ add_library(ext-gtest INTERFACE) ++ if (${CMAKE_VERSION} VERSION_LESS "3.20.0") ++ target_link_libraries(ext-gtest INTERFACE GTest::GTest GTest::Main) ++ else() ++ target_link_libraries(ext-gtest INTERFACE GTest::gtest GTest::gtest_main) ++ endif() + endif() + endif() diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/package.py new file mode 100644 index 0000000..3b320f9 --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/oomph/package.py @@ -0,0 +1,109 @@ +from spack.package import * + + +class Oomph(CMakePackage, CudaPackage, ROCmPackage): + """Oomph is a non-blocking callback-based point-to-point communication library.""" + + homepage = "https://github.com/ghex-org/oomph" + url = "https://github.com/ghex-org/oomph/archive/refs/tags/v0.2.0.tar.gz" + git = "https://github.com/ghex-org/oomph.git" + maintainers = ["boeschf"] + + version("0.4.0", sha256="e342c872dfe4832be047f172dc55c12951950c79da2630b071c61607ef913144") + version("0.3.0", sha256="61e346d1ba28a859745de47f37edce39c7f5c5e1aab716493dc964e158fd99ec") + version("0.2.0", sha256="135cdb856aa817c053b6af1617869dbcd0ee97d34607e78874dd775ea389434e") + version("0.1.0", sha256="0ff36db0a5f30ae1bb02f6db6d411ea72eadd89688c00f76b4e722bd5a9ba90b") + version("main", branch="main") + + depends_on("cxx", type="build") + depends_on("fortran", type="build", when="+fortran-bindings") + + generator("ninja") + + backends = ("mpi", "ucx", "libfabric") + variant( + "backend", default="mpi", description="Transport backend", values=backends, multi=False + ) + + variant("fortran-bindings", default=False, description="Build Fortran bindings") + with when("+fortran-bindings"): + variant( + "fortran-fp", + default="float", + description="Floating point type", + values=("float", "double"), + multi=False, + ) + variant("fortran-openmp", default=True, description="Compile with OpenMP") + + variant( + "enable-barrier", + default=True, + description="Enable thread barrier (disable for task based runtime)", + ) + + depends_on("hwmalloc+cuda", when="+cuda") + depends_on("hwmalloc+rocm", when="+rocm") + depends_on("hwmalloc", when="~cuda~rocm") + + with when("backend=ucx"): + depends_on("ucx+thread_multiple") + depends_on("ucx+cuda", when="+cuda") + depends_on("ucx+rocm", when="+rocm") + variant("use-pmix", default="False", description="Use PMIx to establish out-of-band setup") + variant("use-spin-lock", default="False", description="Use pthread spin locks") + depends_on("pmix", when="+use-pmix") + + libfabric_providers = ("cxi", "efa", "gni", "psm2", "tcp", "verbs") + with when("backend=libfabric"): + variant( + "libfabric-provider", + default="tcp", + description="fabric", + values=libfabric_providers, + multi=False, + ) + for provider in libfabric_providers: + depends_on(f"libfabric fabrics={provider}", when=f"libfabric-provider={provider}") + + depends_on("mpi") + depends_on("boost+thread") + + depends_on("googletest", type=("build","test")) + + patch("install_0.2.patch", when="@:0.2.0", level=1) + patch("install_0.3.patch", when="@0.3.0", level=1) + + def cmake_args(self): + args = [ + self.define_from_variant("OOMPH_BUILD_FORTRAN", "fortran-bindings"), + self.define_from_variant("OOMPH_FORTRAN_OPENMP", "fortran-openmp"), + self.define_from_variant("OOMPH_UCX_USE_PMI", "use-pmix"), + self.define_from_variant("OOMPH_UCX_USE_SPIN_LOCK", "use-spin-lock"), + self.define_from_variant("OOMPH_ENABLE_BARRIER", "enable-barrier"), + self.define("OOMPH_WITH_TESTING", self.run_tests), + self.define("OOMPH_GIT_SUBMODULE", False), + self.define("OOMPH_USE_BUNDLED_LIBS", False), + ] + + if self.run_tests and self.spec.satisfies("^openmpi"): + args.append(self.define("MPIEXEC_PREFLAGS", "--oversubscribe")) + + if self.spec.variants["fortran-bindings"].value == True: + args.append(self.define("OOMPH_FORTRAN_FP", self.spec.variants["fortran-fp"].value)) + + for backend in self.backends: + args.append( + self.define( + f"OOMPH_WITH_{backend.upper()}", self.spec.variants["backend"].value == backend + ) + ) + + if self.spec.satisfies("backend=libfabric"): + args.append( + self.define( + "OOMPH_LIBFABRIC_PROVIDER", self.spec.variants["libfabric-provider"].value + ) + ) + + return args diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/py-cupy/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/py-cupy/package.py new file mode 100644 index 0000000..e2be01e --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/py-cupy/package.py @@ -0,0 +1,145 @@ +# Copyright Spack Project Developers. See COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +import os + +from spack.package import * + + +class PyCupy(PythonPackage, CudaPackage, ROCmPackage): + """CuPy is an open-source array library accelerated with + NVIDIA CUDA. CuPy provides GPU accelerated computing with + Python. CuPy uses CUDA-related libraries including cuBLAS, + cuRand, cuSolver, cuSPARSE, cuFFT and NCCL to make + full use of the GPU architecture. + + This version does not use CudNN.""" + + homepage = "https://cupy.dev/" + pypi = "cupy/cupy-8.0.0.tar.gz" + + # version( + # "13.5.1", + # sha256="3dba2f30258463482d52deb420862fbbbaf2c446165a5e8d67377ac6cb5c0870", + # ) + version( + "13.1.0", + sha256="5caf62288481a27713384523623045380ff42e618be4245f478238ed1786f32d", + ) + version( + "12.1.0", + sha256="f6d31989cdb2d96581da12822e28b102f29e254427195c2017eac327869b7320", + ) + version( + "12.0.0", + sha256="61ddbbef73d50d606bd5087570645f3c91ec9176c2566784c1d486d6a3404545", + ) + version( + "11.6.0", + sha256="53dbb840072bb32d4bfbaa6bfa072365a30c98b1fcd1f43e48969071ad98f1a7", + ) + version( + "11.5.0", + sha256="4bc8565bded22cc89b210fd9fb48a5d5316f30701e12bb23852a60314e1f9f6e", + ) + version( + "11.4.0", + sha256="03d52b2626e02a3a2b46d714c1cd03e702c8fe33915fcca6ed8de5c539964f49", + ) + version( + "11.3.0", + sha256="d057cc2f73ecca06fae8b9c270d9e14116203abfd211a704810cc50a453b4c9e", + ) + version( + "11.2.0", + sha256="c33361f117a347a63f6996ea97446d17f1c038f1a1f533e502464235076923e2", + ) + + variant( + "all", default=False, description="Enable optional py-scipy, optuna, and cython" + ) + + depends_on("cxx", type="build") # generated + + depends_on("python@3.7:", when="@:11", type=("build", "run")) + depends_on("python@3.8:", when="@12:", type=("build", "run")) + depends_on("py-setuptools", type="build") + depends_on("py-cython@0.29.22:2", type="build") + depends_on("py-fastrlock@0.5:", type=("build", "run")) + depends_on("py-numpy@1.20:1.25", when="@:11", type=("build", "run")) + depends_on("py-numpy@1.20:1.26", when="@12:", type=("build", "run")) + depends_on("py-numpy@1.22:1.28", when="@13:", type=("build", "run")) + + depends_on("py-scipy@1.6:1.12", when="@:12+all", type=("build", "run")) + depends_on("py-scipy@1.7:1.13", when="@13:+all", type=("build", "run")) + depends_on("py-cython@0.29.22:2", when="+all", type=("build", "run")) + depends_on("py-optuna@2:", when="+all", type=("build", "run")) + + # Based on https://github.com/cupy/cupy/releases + depends_on("cuda@:11.9", when="@:11 +cuda") + depends_on("cuda@:12.1", when="@12:12.1.0 +cuda") + depends_on("cuda@:12.4", when="@13:13.4.1 +cuda") + depends_on("cuda@:12.9", when="@13.5.1: +cuda") + + for a in CudaPackage.cuda_arch_values: + depends_on( + "nccl +cuda cuda_arch={0}".format(a), when="+cuda cuda_arch={0}".format(a) + ) + + depends_on("cutensor", when="@:12.1.0 +cuda") + depends_on("cutensor@2.0.1.2", when="@13.1: +cuda") + + for _arch in ROCmPackage.amdgpu_targets: + arch_str = "amdgpu_target={0}".format(_arch) + rocm_str = "+rocm {0}".format(arch_str) + depends_on("rocprim {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocsolver {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocthrust {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("rocrand {0}".format(arch_str), when=rocm_str, type=("link")) + depends_on("hipcub {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipblas {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hiprand {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipsparse {0}".format(rocm_str), when=rocm_str, type=("link")) + depends_on("hipfft {0}".format(rocm_str), when=rocm_str, type=("link")) + + depends_on("rccl", when="+rocm", type=("link")) + depends_on("roctracer-dev", when="+rocm", type=("link")) + depends_on("rocprofiler-dev", when="+rocm", type=("link")) + + conflicts("~cuda ~rocm") + conflicts("+cuda +rocm") + conflicts("+cuda cuda_arch=none") + + def setup_build_environment(self, env): + env.set("CUPY_NUM_BUILD_JOBS", make_jobs) + if self.spec.satisfies("+cuda"): + cuda_arch = self.spec.variants["cuda_arch"].value + arch_str = ";".join( + "arch=compute_{0},code=sm_{0}".format(i) for i in cuda_arch + ) + env.set("CUPY_NVCC_GENERATE_CODE", arch_str) + elif self.spec.satisfies("+rocm"): + spec = self.spec + + incs = { + "roctracer-dev": ["include/roctracer"], + "hiprand": ["include"], + "rocrand": ["include"], + "rocthrust": ["include"], + "rocprim": ["include"], + "hip": ["include", "include/hip"], + } + + inc_dirs = [] + for pkg, ds in incs.items(): + for d in ds: + p = os.path.join(spec[pkg].prefix, d) + if os.path.exists(p): + inc_dirs.append(p) + + env.set("CUPY_INCLUDE_PATH", ":".join(inc_dirs)) + + env.set("HIPCC", self.spec["hip"].hipcc) + env.set("ROCM_HOME", self.spec["hipcub"].prefix) + env.set("CUPY_INSTALL_USE_HIP", 1) diff --git a/recipes/icon-dsl/25.8/gh200/repo/packages/uv/package.py b/recipes/icon-dsl/25.8/gh200/repo/packages/uv/package.py new file mode 100644 index 0000000..6941eff --- /dev/null +++ b/recipes/icon-dsl/25.8/gh200/repo/packages/uv/package.py @@ -0,0 +1,68 @@ +from spack.package import * + + +def translate_platform(platform_name: str) -> str: + if platform_name == "darwin": + return "apple-darwin" + elif platform_name == "linux": + return "unknown-linux-gnu" + return platform_name + + +def translate_arch(arch_name: str) -> str: + if arch_name in ["m1", "m2", "neoverse_v2"]: + return "aarch64" + if arch_name in ["zen3"]: + return "x86_64" + return arch_name + + +class Uv(Package): + """Install UV from binary releases""" + + url = "https://github.com/astral-sh/uv/releases/download/0.7.12/uv-aarch64-apple-darwin.tar.gz" + + version( + "0.7.12", + sha256="189108cd026c25d40fb086eaaf320aac52c3f7aab63e185bac51305a1576fc7e", + extension=".tar.gz", + ) + version( + "0.7.20", + sha256="675165f879d6833aa313ecb25ac44781e131933a984727e180b3218d2cd6c1e9", + extension=".tar.gz", + ) + + def url_for_version(self, version): + arch = translate_arch(self.spec.target) + platform = translate_platform(self.spec.platform) + return f"https://github.com/astral-sh/uv/releases/download/{version}/uv-{arch}-{platform}.tar.gz" + + def do_stage(self, mirror_only=False): + checksums = { + ("0.7.12", "apple-darwin", "aarch64"): ( + "189108cd026c25d40fb086eaaf320aac52c3f7aab63e185bac51305a1576fc7e" + ), + ("0.7.20", "unknown-linux-gnu", "aarch64"): ( + "675165f879d6833aa313ecb25ac44781e131933a984727e180b3218d2cd6c1e9" + ), + ("0.7.20", "unknown-linux-gnu", "x86_64"): ( + "10f204426ff188925d22a53c1d0310d190a8d4d24513712e1b8e2ca9873f0666" + ), + } + version = str(self.spec.version) + arch = translate_arch(self.spec.target) + platform = translate_platform(self.spec.platform) + key = (version, platform, arch) + + if key not in checksums: + msg = f"Unsupported platform/arch for version {version}: {platform}-{arch}." + raise InstallError(msg) + + self.fetcher.digest = checksums[key] + super().do_stage(mirror_only) + + def install(self, spec, prefix): + mkdir(prefix.bin) + install("uv", prefix.bin.uv) + install("uvx", prefix.bin.uvx) diff --git a/recipes/icon-dsl/README.md b/recipes/icon-dsl/README.md new file mode 100644 index 0000000..bb7fc25 --- /dev/null +++ b/recipes/icon-dsl/README.md @@ -0,0 +1,2 @@ +# ICON-DSL UENV +Experimental ALPS user environment for running icon-exclaim with DSL dycore.