summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/libmesh/package.py
blob: bdc882716998543cde92b95ba68b7c76a67e8e2a (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# Copyright 2013-2019 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 Libmesh(AutotoolsPackage):
    """The libMesh library provides a framework for the numerical simulation of
       partial differential equations using arbitrary unstructured
       discretizations on serial and parallel platforms."""

    homepage = "http://libmesh.github.io/"
    url      = "https://github.com/libMesh/libmesh/releases/download/v1.0.0/libmesh-1.0.0.tar.bz2"
    git      = "https://github.com/libMesh/libmesh.git"

    version('1.3.1', sha256='638cf30d05c249315760f16cbae4804964db8857a04d5e640f37617bef17ab0f')
    version('1.3.0', sha256='a8cc2cd44f42b960989dba10fa438b04af5798c46db0b4ec3ed29591b8359786')
    version('1.2.1', sha256='11c22c7d96874a17de6b8c74caa45d6745d40bf3610e88b2bd28fd3381f5ba70')
    version('1.0.0', 'cb464fc63ea0b71b1e69fa3f5d4f93a4')

    # support for libraries that are only available through the bundled copies:
    # TODO libMesh 1.2.1 gained the ability to specify a path to capnproto
    variant('capnproto', default=False, description='Compile with the bundled capnproto serialization library')
    variant('exodusii', default=False, description='Compile with the bundled ExodusII output library')
    variant('vtk', default=False, description='Compile with  VTK input/output library')
    variant('fparser', default=False, description='Compile with the bundled fparser function parser library')
    variant('gmv', default=False, description='Compile with the bundled gmv format IO library')
    variant('laspack', default=False, description='Compile with the bundled laspack interative solver library')
    variant('libhilbert', default=False, description='Compile with the bundled libHilbert partitioning library')
    variant('metaphysicl', default=False, description='Compile with the bundled metaphysicl AD library')
    variant('metis', default=False, description='Compile with the bundled METIS graph partitioning library')
    variant('nanoflann', default=False, description='Compile with the bundled nanoflann graph library')
    variant('nemesis', default=False, description='Compile with the bundled nemesis IO library')
    variant('netcdf', default=False, description='Compile with the bundled NETCDF IO library')
    # TODO the copy of parmetis bundled with libMesh assumes that we use the
    # bundled copy of metis, but previous versions of this build script use an
    # external metis installation. Be conservative and completely disable
    # parmetis support to preserve the old behavior (and to prevent compiling
    # with two different copies of metis).
    #
    # variant('parmetis', default=False,
    #         description='Compile with the bundled PARMETIS graph library')
    variant('qhull', default=False, description='Compile with the bundled qhull mesh generation library')
    variant('sfc', default=False, description='Compile with the bundled sfcurves partitioning library')
    variant('tetgen', default=False, description='Compile with the bundled tetgen mesh generation library')
    variant('triangle', default=False, description='Compile with the bundled Triangle mesh generation library')

    # support for libraries that may be externally installed:
    variant('boost', default=False, description='Compile with components dependent on boost')
    variant('eigen', default=False, description='support for dense linear algebra with Eigen')
    variant('hdf5', default=False, description='Compile with support for HDF5 files')
    variant('slepc', default=False, description='Compile with support for the SLEPc eigensolver')
    variant('petsc', default=False, description='Compile with support for the PETSc')

    # other features:
    variant('debug', default=False, description='Compile with support for debugging')
    variant('mpi', default=True, description='Enables MPI parallelism')
    # While it is possible to configure libMesh to use openMP with neither
    # pthreads nor TBB, no openMP code can actually be reached without enabling
    # pthreads as well. Hence, since enabling openMP while disabling pthreads
    # is not useful, we include openMP in the same variant to make it clear
    # which scheduler is ultimately used.
    variant('threads', default='none',
            description='Enable threading support (with a particular '
            'scheduler, in the case of openmp and tbb)',
            values=('none', 'pthreads', 'tbb', 'openmp'), multi=False)

    conflicts('+metaphysicl', when='@:1.2.999',
              msg='The interface to metaphysicl is not available in libMesh '
              'versions older than 1.3.0. Please explicitly disable this '
              'variant.')

    depends_on('boost', when='+boost')
    # The Scotch dependency of Eigen is not used by libMesh. Since Scotch can
    # only be used with certain versions of flex it conflicts with several
    # versions of GCC, so explicitly disable it.
    depends_on('eigen~scotch', when='+eigen')
    depends_on('hdf5+mpi', when='+hdf5+mpi')
    depends_on('mpi', when='+mpi')
    depends_on('mpi', when='+slepc')
    # compilation dependencies depend on perl
    depends_on('perl')
    depends_on('petsc+mpi', when='+mpi')
    depends_on('petsc+metis', when='+metis')
    depends_on('slepc', when='+slepc')
    depends_on('petsc', when='+petsc')
    depends_on('tbb', when='threads=tbb')
    depends_on('vtk', when='+vtk')

    def configure_args(self):
        options = []

        # GLIBCXX debugging is not, by default, supported by other libraries,
        # so unconditionally disable it for libmesh
        options.append('--enable-glibcxx-debugging=no')

        # All bundled dependencies are explicitly disabled, so we do not need
        # to perform this check:
        options.append('--disable-strict-lgpl')

        # The Hinnant unique pointer implementation is incompatible with boost
        # (and not necessary with C++11 support), so unconditionally disable
        # it:
        options.append('--disable-hinnant-unique-ptr')
        # libMesh does not allow for us to specify an installation location for
        # zlib, an undocumented dependency of gzstreams: hence we must
        # unconditionally disable gzstreams.
        options.append('--enable-gzstreams=no')
        # Similarly, since we cannot specify a location for bzip2 or xz, so
        # disable them to avoid picking up system installations:
        options.append('--disable-bzip2')
        options.append('--disable-xz')
        # TODO enable GDB backtracing. Disable for now to avoid picking up the
        # system gdb installation:
        options.append('--without-gdb-command')

        # TODO add X11 as a dependency to get tecplot working
        options.append('--enable-tecio=no')
        options.append('--enable-tecplot=no')

        # handle the bundled libraries that are not themselves dependencies of
        # other bundled libaries:
        for bundled_library in ['capnproto', 'exodusii', 'fparser', 'gmv',
                                'laspack', 'libHilbert', 'metaphysicl',
                                'nanoflann', 'nemesis', 'parmetis', 'qhull',
                                'sfc', 'tetgen', 'triangle']:
            if '+' + bundled_library.lower() in self.spec:
                options.append('--enable-' + bundled_library + "=yes")
            else:
                options.append('--enable-' + bundled_library + "=no")

        # and the ones which are dependencies of other bundled libraries:
        if '+exodusii' in self.spec or '+netcdf' in self.spec:
            options.append('--enable-netcdf=yes')
        else:
            options.append('--enable-netcdf=no')

        if '+vtk' in self.spec:
            options.append('--enable-vtk')
            options.append('--with-vtk=%s' % self.spec['vtk'].prefix)
        else:
            options.append('--disable-vtk')

        # handle external library dependencies:
        if '+boost' in self.spec:
            options.append('--with-boost=%s' % self.spec['boost'].prefix)
        else:
            options.append('--enable-boost=no')

        if '+eigen' in self.spec:
            options.append('--with-eigen=%s' % self.spec['eigen'].prefix)
        else:
            options.append('--enable-eigen=no')

        if '+hdf5' in self.spec:
            options.append('--with-hdf5=%s' % self.spec['hdf5'].prefix)
        else:
            options.append('--enable-hdf5=no')
            # This is necessary with libMesh 1.2.1 to prevent a configure
            # error:
            if '+netcdf' not in self.spec:
                options.append('--disable-netcdf-4')

        if '+metis' in self.spec:
            options.append('--with-metis=PETSc')

        if '+petsc' in self.spec or '+slepc' in self.spec:
            options.append('--enable-petsc=yes')
            options.append('PETSC_DIR=%s' % self.spec['petsc'].prefix)
        else:
            options.append('--enable-petsc=no')

        if '+slepc' in self.spec:
            options.append('--enable-slepc=yes')
            options.append('SLEPC_DIR=%s' % self.spec['slepc'].prefix)
        else:
            options.append('--enable-slepc=no')

        # and, finally, other things:
        if '+debug' in self.spec:
            options.append('--with-methods=dbg')
        else:
            options.append('--with-methods=opt')

        if '+mpi' in self.spec:
            options.append('CC=%s' % self.spec['mpi'].mpicc)
            options.append('CXX=%s' % self.spec['mpi'].mpicxx)
            options.append('--with-mpi=%s' % self.spec['mpi'].prefix)
        else:
            options.append('--disable-mpi')
            # libMesh will try to link with the system MPI library unless we
            # provide explicit overrides
            options.append('CC=%s' % self.compiler.cc)
            options.append('CXX=%s' % self.compiler.cxx)

        if 'threads=openmp' in self.spec:
            # OpenMP cannot be used if pthreads is not available: see
            # parallel/threads_pthread.h and parallel/threads.h
            options.append('--enable-openmp=yes')
            options.append('--with-thread-model=pthread')
            options.append('--enable-pthreads=yes')
        else:
            options.append('--enable-openmp=no')

        if 'threads=pthreads' in self.spec:
            options.append('--with-thread-model=pthread')
            options.append('--enable-pthreads=yes')
        else:
            if 'threads=openmp' not in self.spec:
                options.append('--enable-pthreads=no')

        if 'threads=tbb' in self.spec:
            options.append('--with-thread-model=tbb')
            options.append('--enable-tbb=yes')
            options.append('--with-tbb=%s' % self.spec['tbb'].prefix)
        else:
            options.append('--enable-tbb=no')

        return options

    def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
        spack_env.append_flags('PERL', self.spec['perl'].command.path)