summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/ffte/package.py
blob: ed6de99aa4c2c7ad3a24870192169f4618e156e4 (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
# Copyright 2013-2023 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)

import glob

from spack.package import *


class Ffte(Package):
    """Fastest Fourier Transform in the East. Provides FFT for powers of 2, 3,
    and 5 lengths in one, two, and three dimensions. Support for vector
    hardware, MPI, and CUDA Fortran is also included."""

    homepage = "http://www.ffte.jp/"
    url = "http://www.ffte.jp/ffte-7.0.tgz"

    maintainers("luszczek")

    version("7.0", sha256="078d5f84a5f2479ca5c4a3bd777ad761fe98addf1642a045bac6602a0cae3da0")
    version("6.0", sha256="fc82595a8f8323b2796cc5eeb1cc9f7e50ca9e511a14365cc3984da6b7a9b8b4")
    version("5.0", sha256="1f46ca16badc3aca0ad13ca91a6a67829a57b403501cdc821b80cfa62b2a89c2")
    version("4.0", sha256="61680f73c48659ac45aec60ef5a725547f763bb9017edbd3f44a6a9ad0fda62f")
    version("3.0", sha256="dbaab8204a16072c8d572efa3733e9946a9be0d1a051fc19e2d9253be23247ff")
    version("2.0", sha256="f5cf1d1f880288e359f4d517191980ffca4420f817ecaa2d754ca5c5421271e3")
    version("1.0", sha256="35171e3324019018c25575b2807a6513fa85badad040f30f238fff03d4b4d1ab")

    variant("mpi", default=False, description="Build MPI library")
    variant("cuda", default=False, description="Use CUDA Fortran")
    variant("vector", default=False, description="Use vectorized FFT")

    depends_on("mpi", when="+mpi")

    requires("%nvhpc", when="+cuda", msg="ffte+cuda must use NVHPC compiler")

    def edit(self, spec, prefix):
        "No make-file, must create one from scratch."

        open("mpi/param.h", "w").write(open("param.h").read())

        for fpfx in (".", "mpi"):
            vrs = "%sfftever" % ["", "", "", "p"][len(fpfx)]
            s6 = 6 * " "
            fd = open("%s/%s.f" % (fpfx, vrs), "w")
            fd.write("%ssubroutine %s(i,j,k)\n" % (s6, vrs))
            fd.write("%sinteger i,j,k\n" % s6)
            fd.write("%si=%s\n" % (s6, spec.version[0]))
            fd.write("%sj=%s\n" % (s6, spec.version[1]))
            fd.write("%sk=0\n%sreturn\n%send\n" % (3 * (s6,)))
            fd.close()

            ff, cuf, vf = [], [], []
            for f in glob.glob("%s/*.f" % fpfx):
                nf = f.replace(".f", ".o").replace("%s/" % fpfx, "")
                if "/cu" in f or "/pcu" in f:
                    cuf.append(nf)
                elif "/v" in f or "/pv" in f:
                    vf.append(nf)
                else:
                    ff.append(nf)

            if "." == fpfx:
                lbnm = "libffte.a"
            else:
                lbnm = "libfftempi.a"

            for spc, vrf, rs, ip in (("+vector", vf, "v", 2), ("+cuda", cuf, "cu", 3)):
                if spc in spec:
                    for f in vrf:  # replace with variant versions
                        orgf = f[:ip].replace(rs, "") + f[ip:]
                        if orgf in ff:  # already reference implementation?
                            del ff[ff.index(orgf)]
                    ff.extend(vrf)

            aff = " ".join(ff)
            fd = open("%s/Makefile" % fpfx, "w")
            fd.write("all: %s\n" % lbnm)
            if "+mpi" in spec and "." == fpfx:
                fd.write("\tcd mpi ; $(MAKE)\n")
            fd.write("\n%s: %s\n" % (lbnm, aff))
            fd.write("\tar rc %s %s\n" % (lbnm, aff))
            fd.write("\tranlib %s\n" % lbnm)
            fd.close()

    def install(self, spec, prefix):
        self.edit(spec, prefix)
        if "+mpi" in spec:
            env["CC"] = spec["mpi"].mpicc
            env["F77"] = spec["mpi"].mpif77
            env["FC"] = spec["mpi"].mpifc

        # allow real/complex aliasing in GNU Fortran 10 and up
        if spec.satisfies("%gcc@10:"):
            env["FFLAGS"] = "-fallow-argument-mismatch"

        # enable CUDA Fortran in NVHPC
        if spec.satisfies("%nvhpc"):
            env["FFLAGS"] = "-Mcuda"

        make()
        mkdirp(prefix.lib)
        install("libffte.a", prefix.lib)
        if "+mpi" in spec:
            install("mpi/libfftempi.a", prefix.lib)