diff --git a/pkgs/development/python-modules/libmobility/default.nix b/pkgs/development/python-modules/libmobility/default.nix new file mode 100644 index 000000000000..bb4b74e1ffe7 --- /dev/null +++ b/pkgs/development/python-modules/libmobility/default.nix @@ -0,0 +1,170 @@ +{ + lib, + config, + buildPythonPackage, + fetchFromGitHub, + python, + + # build-system + cmake, + nanobind, + setuptools, + + # nativeBuildInputs + autoAddDriverRunpath, + cudaPackages, + + # buildInputs + blas, + lapack, + + # dependencies + numpy, + scipy, + + # tests + pytest-xdist, + pytestCheckHook, + + # passthru + libmobility, +}: +let + uammd-src = fetchFromGitHub { + owner = "RaulPPelaez"; + repo = "uammd"; + tag = "v3.0.1"; + hash = "sha256-/7ceXlA96dZQs1WzkV1OpRv61xa0Tdt5gFe17I0s1BI="; + }; +in +buildPythonPackage.override { stdenv = cudaPackages.backendStdenv; } (finalAttrs: { + pname = "libmobility"; + version = "1.1.2"; + pyproject = true; + __structuredAttrs = true; + + src = fetchFromGitHub { + owner = "stochasticHydroTools"; + repo = "libMobility"; + tag = "v${finalAttrs.version}"; + hash = "sha256-7jUpVR4bS9vkgeKN68of6VNZzGPlQMcRMBStQ+wFEx4="; + }; + + postPatch = + # Various setup.py patches: + # - Inject nix's cmakeFlags + # - Patch install destination + # - Don't let setuptools ship the `solvers/` directory as the package is + # already installed by cmake + # - Patch the version + '' + substituteInPlace setup.py \ + --replace-fail \ + "cmake_args = [" \ + "cmake_args = [${lib.concatStringsSep "," (map (f: "'${f}'") finalAttrs.cmakeFlags)}," \ + --replace-fail \ + "sys.prefix" \ + 'os.environ["out"]' \ + --replace-fail \ + "packages=find_packages()," \ + "packages=[]," \ + --replace-fail \ + 'version = "0"' \ + 'version = "${finalAttrs.version}"' + '' + # Upstream installs the modules into the (read-only) absolute `Python_SITEARCH`. + # Make the destination relative so it lands under CMAKE_INSTALL_PREFIX ($out). + + '' + substituteInPlace solvers/CMakeLists.txt \ + --replace-fail "$""{Python_SITEARCH}" "${python.sitePackages}" + '' + # The C++ test suite unconditionally fetches googletest over the network and + # is not run here (it requires a GPU); drop it. + + '' + substituteInPlace CMakeLists.txt \ + --replace-fail "add_subdirectory(tests/cpp)" "" + ''; + + build-system = [ + cmake + nanobind + setuptools + ]; + dontUseCmakeConfigure = true; + + nativeBuildInputs = [ + autoAddDriverRunpath + cudaPackages.cuda_nvcc + ]; + + cmakeFlags = [ + (lib.cmakeFeature "FETCHCONTENT_SOURCE_DIR_UAMMD" uammd-src.outPath) + (lib.cmakeFeature "nanobind_DIR" "${nanobind}/${python.sitePackages}/nanobind/cmake") + ]; + + env = { + CMAKE_CUDA_ARCHITECTURES = cudaPackages.flags.cmakeCudaArchitecturesString; + }; + + preBuild = '' + export BUILD_JOBS="$NIX_BUILD_CORES" + ''; + + buildInputs = [ + blas + lapack + ] + ++ (with cudaPackages; [ + cuda_cccl # + cuda_cudart # CUDA::cuda_driver (driver stub) + libcublas + libcufft + libcurand + libcusolver + ]); + + dependencies = [ + numpy + scipy + ]; + + pythonImportsCheck = [ "libMobility" ]; + + nativeCheckInputs = [ + pytest-xdist + pytestCheckHook + ]; + + disabledTests = [ + # FileNotFoundError: [Errno 2] No such file or directory: './ref/pair_mobility_nbody_freespace.npz' + "test_pair_mobility_angular_nbody" + + # AssertionError (numerical assertion) + "test_deterministic_divM_matches_rfd" + "test_non_square_box" + + # TypeError: Iterator operand 1 dtype could not be cast from dtype('complex128') to + # dtype('float64') according to the rule 'safe' + "test_fluctuation_dissipation_angular_displacements" + + # Extremely long + "test_fluctuation_dissipation_linear_displacements" + ]; + + # Tests require GPU access + doCheck = false; + passthru.gpuCheck = libmobility.overridePythonAttrs { + requiredSystemFeatures = [ "cuda" ]; + doCheck = true; + }; + + meta = { + description = "Python interface to a collection of GPU hydrodynamic mobility solvers"; + homepage = "https://github.com/stochasticHydroTools/libMobility"; + changelog = "https://github.com/stochasticHydroTools/libMobility/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ GaetanLepage ]; + platforms = lib.platforms.linux; + broken = !config.cudaSupport; + }; +}) diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 0b679e3516fd..ec921baa61cb 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -8897,6 +8897,8 @@ self: super: with self; { libmambapy = callPackage ../development/python-modules/libmambapy { }; + libmobility = callPackage ../development/python-modules/libmobility { }; + libmodulemd = lib.pipe pkgs.libmodulemd [ toPythonModule (