# Copyright 2013-2022 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 * 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" 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)