summaryrefslogtreecommitdiff
path: root/var/spack/repos/builtin/packages/libmesh/package.py
blob: 6f262646144c670c142d55e1b2329dcecfc66853 (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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# Copyright 2013-2024 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.package import *
from spack.pkg.builtin.boost import Boost


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 = "https://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"

    license("LGPL-2.1-or-later")

    version("master", branch="master", submodules=True)

    version("1.4.1", sha256="67eb7d5a9c954d891ca1386b70f138333a87a141d9c44213449ca6be69a66414")
    version("1.4.0", sha256="62d7fce89096c950d1b38908484856ea63df57754b64cde6582e7ac407c8c81d")
    version("1.3.1", sha256="638cf30d05c249315760f16cbae4804964db8857a04d5e640f37617bef17ab0f")
    version("1.3.0", sha256="a8cc2cd44f42b960989dba10fa438b04af5798c46db0b4ec3ed29591b8359786")
    version("1.2.1", sha256="11c22c7d96874a17de6b8c74caa45d6745d40bf3610e88b2bd28fd3381f5ba70")
    version("1.0.0", sha256="8909b0354e147fa50d176caa63ef22b02326d49250e964be23532d89432e727f")

    # 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("perflog", default=False, description="Compile with performance logging support")
    variant("blocked", default=False, description="Compile with support for blocked storage")
    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",
        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")

    # TODO: replace this with an explicit list of components of Boost,
    # for instance depends_on('boost +filesystem')
    # See https://github.com/spack/spack/pull/22303 for reference
    depends_on(Boost.with_default_variants, when="+boost")
    depends_on("eigen", 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 "+metaphysicl" in self.spec:
            options.append("--enable-metaphysicl")
        else:
            options.append("--disable-metaphysicl")

        if "+perflog" in self.spec:
            options.append("--enable-perflog")
        else:
            options.append("--disable-perflog")

        if "+blocked" in self.spec:
            options.append("--enable-blocked-storage")
        else:
            options.append("--disable-blocked-storage")

        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("--enable-metis")
            options.append("--enable-parmetis")
            if "+petsc" in self.spec:
                options.append("--with-metis=PETSc")
                options.append("--with-parmetis=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_build_environment(self, env, dependent_spec):
        env.append_flags("PERL", self.spec["perl"].command.path)