summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/mfem/package.py
blob: 510e09c4e112facc2dbc422c43f11b9b91b1d49f (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
from spack import *
import glob, string

class Mfem(Package):
    """Free, lightweight, scalable C++ library for finite element methods."""

    homepage = 'http://www.mfem.org'
    url      = 'https://github.com/mfem/mfem'

#    version('3.1', git='https://github.com/mfem/mfem.git',
#            commit='dbae60fe32e071989b52efaaf59d7d0eb2a3b574')

    version('3.1', '841ea5cf58de6fae4de0f553b0e01ebaab9cd9c67fa821e8a715666ecf18fc57',
            url='http://goo.gl/xrScXn', expand=False)

    variant('metis', default=False, description='Activate support for metis')
    variant('hypre', default=False, description='Activate support for hypre')
    variant('suite-sparse', default=False,
            description='Activate support for SuiteSparse')
    variant('mpi', default=False, description='Activate support for MPI')
    variant('lapack', default=False, description='Activate support for LAPACK')
    variant('debug', default=False, description='Build debug version')

    depends_on('blas', when='+lapack')
    depends_on('lapack', when='+lapack')

    depends_on('mpi', when='+mpi')
    depends_on('metis', when='+mpi')
    depends_on('hypre', when='+mpi')

    depends_on('hypre', when='+hypre')

    depends_on('metis@4:', when='+metis')

    depends_on('suite-sparse', when='+suite-sparse')
    depends_on('blas', when='+suite-sparse')
    depends_on('lapack', when='+suite-sparse')
    depends_on('metis@5:', when='+suite-sparse ^suite-sparse@4.5:')
    depends_on('cmake', when='^metis@5:')

    def check_variants(self, spec):
        if '+mpi' in spec and ('+hypre' not in spec or '+metis' not in spec):
            raise InstallError('mfem+mpi must be built with +hypre ' +
                               'and +metis!')
        if '+suite-sparse' in spec and ('+metis' not in spec or
                                        '+lapack' not in spec):
            raise InstallError('mfem+suite-sparse must be built with ' +
            '+metis and +lapack!')
        if 'metis@5:' in spec and '%clang' in spec and ('^cmake %gcc' not in spec):
            raise InstallError('To work around CMake bug with clang, must ' +
                               'build mfem with mfem[+variants] %clang ' +
                               '^cmake %gcc to force CMake to build with gcc')
        return

    def install(self, spec, prefix):
        self.check_variants(spec)

        options = ['PREFIX=%s' % prefix]

        if '+lapack' in spec:
            lapack_lib = '-L{0} -llapack -L{1} -lblas'.format(
                spec['lapack'].prefix.lib, spec['blas'].prefix.lib)
            options.extend(['MFEM_USE_LAPACK=YES',
                            'LAPACK_OPT=-I%s' % spec['lapack'].prefix.include,
                            'LAPACK_LIB=%s' % lapack_lib])

        if '+hypre' in spec:
            options.extend(['HYPRE_DIR=%s' % spec['hypre'].prefix,
                            'HYPRE_OPT=-I%s' % spec['hypre'].prefix.include,
                            'HYPRE_LIB=-L%s' % spec['hypre'].prefix.lib +
                            ' -lHYPRE'])

        if '+metis' in spec:
            metis_lib = '-L%s -lmetis' % spec['metis'].prefix.lib
            if spec['metis'].satisfies('@5:'):
                metis_str = 'MFEM_USE_METIS_5=YES'
            else:
                metis_str = 'MFEM_USE_METIS_5=NO'
            options.extend([metis_str,
                            'METIS_DIR=%s' % spec['metis'].prefix,
                            'METIS_OPT=-I%s' % spec['metis'].prefix.include,
                            'METIS_LIB=%s' % metis_lib])

        if '+mpi' in spec: options.extend(['MFEM_USE_MPI=YES'])

        if '+suite-sparse' in spec:
            ssp = spec['suite-sparse'].prefix
            ss_lib = '-L%s' % ssp.lib
            ss_lib += (' -lumfpack -lcholmod -lcolamd -lamd -lcamd' +
                        ' -lccolamd -lsuitesparseconfig')

            no_librt_archs = ['darwin-i686', 'darwin-x86_64']
            no_rt = any(map(lambda a: spec.satisfies('='+a), no_librt_archs))
            if not no_rt: ss_lib += ' -lrt'
            ss_lib += (' ' + metis_lib + ' ' + lapack_lib)

            options.extend(['MFEM_USE_SUITESPARSE=YES',
                            'SUITESPARSE_DIR=%s' % ssp,
                            'SUITESPARSE_OPT=-I%s' % ssp.include,
                            'SUITESPARSE_LIB=%s' % ss_lib])

        if '+debug' in spec: options.extend(['MFEM_DEBUG=YES'])

        # Dirty hack to cope with URL redirect
        tgz_file = string.split(self.url,'/')[-1]
        tar = which('tar')
        tar('xzvf', tgz_file)
        cd(glob.glob('mfem*')[0])
        # End dirty hack to cope with URL redirect

        make('config', *options)
        make('all')

        # Run a small test before installation
        args = ['-m', join_path('data','star.mesh'), '--no-visualization']
        if '+mpi' in spec:
            Executable(join_path(spec['mpi'].prefix.bin,
                                 'mpirun'))('-np',
                                            '4',
                                            join_path('examples','ex1p'),
                                            *args)
        else:
            Executable(join_path('examples', 'ex1'))(*args)

        make('install')