summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/heffte/package.py
blob: 881280847b7dff1679231bafab67ada3ed4eab23 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Copyright 2013-2021 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 import *


class Heffte(CMakePackage):
    """Highly Efficient FFT for Exascale"""

    homepage = "https://bitbucket.org/icl/heffte"
    url      = "https://bitbucket.org/icl/heffte/get/v1.0.tar.gz"
    git      = "https://bitbucket.org/icl/heffte.git"

    maintainers = ['mkstoyanov']

    test_requires_compiler = True

    version('develop', branch='master')
    version('2.0.0', sha256='12f2b49a1a36c416eac174cf0cc50e729d56d68a9f68886d8c34bd45a0be26b6')
    version('1.0', sha256='0902479fb5b1bad01438ca0a72efd577a3529c3d8bad0028f3c18d3a4935ca74')
    version('0.2', sha256='4e76ae60982b316c2e873b2e5735669b22620fefa1fc82f325cdb6989bec78d1')
    version('0.1', sha256='d279a03298d2dc76574b1ae1031acb4ea964348cf359273d1afa4668b5bfe748')

    patch('threads10.patch', when='@1.0')
    patch('fortran200.patch', when='@2.0.0')

    variant('shared', default=True, description='Builds with shared libraries')
    variant('fftw', default=False, description='Builds with support for FFTW backend')
    variant('mkl',  default=False, description='Builds with support for MKL backend')
    variant('cuda', default=False, description='Builds with support for GPUs via CUDA')
    variant('magma', default=False, description='Use helper methods from the UTK MAGMA library')
    variant('python', default=False, description='Install the Python bindings')
    variant('fortran', default=False, description='Install the Fortran modules')

    depends_on('python@3.0:', when='+python', type=('build', 'run'))
    depends_on('py-mpi4py', when='+python', type=('build', 'run'))
    depends_on('py-numpy', when='+python', type=('build', 'run'))
    depends_on('py-numba', when='+python+cuda', type=('build', 'run'))
    extends('python', when='+python', type=('build', 'run'))

    conflicts('~fftw', when='~mkl~cuda')  # requires at least one backend
    conflicts('+fftw', when='+mkl@:1.0')  # old API supports at most one CPU backend
    conflicts('^openmpi~cuda', when='+cuda')  # +cuda requires CUDA enabled OpenMPI
    conflicts('~cuda', when='+magma')  # magma requires CUDA or HIP
    conflicts('+python', when="@:1.0")  # python support was added post v1.0
    conflicts('+fortran', when="@:1.0")  # fortran support was added post v1.0
    conflicts('+magma', when="@:1.0")  # magma support was added post v1.0

    depends_on('mpi', type=('build', 'run'))

    depends_on('fftw@3.3.8:', when="+fftw", type=('build', 'run'))
    depends_on('intel@16.0:', when="+mkl", type=('build', 'run'))
    depends_on('cuda@8.0:', when="+cuda", type=('build', 'run'))
    depends_on('magma@2.5.3:', when="+cuda+magma", type=('build', 'run'))

    def cmake_args(self):
        return [
            self.define_from_variant('BUILD_SHARED_LIBS', 'shared'),
            self.define_from_variant('Heffte_ENABLE_CUDA', 'cuda'),
            self.define_from_variant('Heffte_ENABLE_FFTW', 'fftw'),
            self.define_from_variant('Heffte_ENABLE_MKL', 'mkl'),
            self.define_from_variant('Heffte_ENABLE_MAGMA', 'magma'),
            self.define_from_variant('Heffte_ENABLE_FORTRAN', 'fortran'),
            self.define_from_variant('Heffte_ENABLE_PYTHON', 'python'),
            '-DBUILD_GPU={0:1s}'.format(
                'ON' if ('+cuda' in self.spec and
                         '+fftw' in self.spec) else 'OFF'), ]

    examples_src_dir = 'examples'

    @run_after('install')
    def cache_test_sources(self):
        """Copy the example source files after the package is installed to an
        install test subdirectory for use during `spack test run`."""
        self.cache_extra_test_sources([self.examples_src_dir])

    def test(self):
        cmake_file = join_path(self.install_test_root, 'CMakeLists.txt')
        test_bld_dir = join_path(self.install_test_root, '_build')
        exe_files = []
        mpi_procs = []

        with open(cmake_file, 'w') as cmkf:
            cmkf.write('cmake_minimum_required(VERSION 3.13)\n\n')
            cmkf.write('project(heffte_example LANGUAGES CXX)\n\n')
            cmkf.write('find_package(Heffte REQUIRED)\n\n')
            if '+fftw' in self.spec:
                src_file = '{0}/heffte_example_fftw.cpp'.format(
                    self.examples_src_dir)
                cmkf.write(
                    'add_executable(hf_fftw {0})\n'.format(src_file))
                cmkf.write(
                    'target_link_libraries(hf_fftw Heffte::Heffte)\n')
                exe_files.append('./hf_fftw')
                mpi_procs.append(4)
            if '+cuda' in self.spec:
                src_file = '{0}/heffte_example_cuda.cpp'.format(
                    self.examples_src_dir)
                cmkf.write(
                    'add_executable(hf_cuda {0})\n'.format(src_file))
                cmkf.write(
                    'target_link_libraries(hf_cuda Heffte::Heffte)\n')
                exe_files.append('./hf_cuda')
                mpi_procs.append(4)
            if '+fortran' in self.spec:
                src_file = '{0}/heffte_example_fftw.f90'.format(
                    self.examples_src_dir)
                cmkf.write(
                    'add_executable(hf_fort {0})\n'.format(src_file))
                cmkf.write(
                    'target_link_libraries(hf_fort Heffte::Fortran)\n')
                exe_files.append('./hf_fort')
                mpi_procs.append(2)

        with working_dir(test_bld_dir, create=True):
            cmake('..')
            make()
            test_args = ['-n', '4', ' ']
            mpiexe_f = which('srun', 'mpirun', 'mpiexec')
            if mpiexe_f:
                for exf, procs in zip(exe_files, mpi_procs):
                    test_args[-1] = exf
                    test_args[-2] = str(procs)
                    reason_str = 'Heffte smoke test, exe: {0}'.format(exf)
                    self.run_test(mpiexe_f.command, test_args,
                                  purpose=reason_str)