Abinit: a few modernizations for the package and its dependencies (#3699)
* libxc: added libs interface * hdf5: added libs interface, added conflicts * abinit: modernized package to use build interface * netcdf-fortran: added libs interface * abinit: added version 8.2.2
This commit is contained in:
parent
030127a071
commit
10c395b2f5
5 changed files with 180 additions and 87 deletions
|
@ -901,16 +901,12 @@ def __init__(self, spec, name, query_parameters):
|
|||
)
|
||||
|
||||
is_virtual = Spec.is_virtual(name)
|
||||
self._query_to_package = QueryState(
|
||||
self.last_query = QueryState(
|
||||
name=name,
|
||||
extra_parameters=query_parameters,
|
||||
isvirtual=is_virtual
|
||||
)
|
||||
|
||||
@property
|
||||
def last_query(self):
|
||||
return self._query_to_package
|
||||
|
||||
|
||||
@key_ordering
|
||||
class Spec(object):
|
||||
|
|
|
@ -28,13 +28,15 @@
|
|||
from spack import *
|
||||
|
||||
|
||||
class Abinit(Package):
|
||||
class Abinit(AutotoolsPackage):
|
||||
"""ABINIT is a package whose main program allows one to find the total
|
||||
energy, charge density and electronic structure of systems made of
|
||||
electrons and nuclei (molecules and periodic solids) within
|
||||
Density Functional Theory (DFT), using pseudopotentials and a planewave
|
||||
or wavelet basis. ABINIT also includes options to optimize the geometry
|
||||
according to the DFT forces and stresses, or to perform molecular dynamics
|
||||
or wavelet basis.
|
||||
|
||||
ABINIT also includes options to optimize the geometry according to the
|
||||
DFT forces and stresses, or to perform molecular dynamics
|
||||
simulations using these forces, or to generate dynamical matrices,
|
||||
Born effective charges, and dielectric tensors, based on Density-Functional
|
||||
Perturbation Theory, and many more properties. Excited states can be
|
||||
|
@ -44,11 +46,12 @@ class Abinit(Package):
|
|||
programs are provided.
|
||||
"""
|
||||
|
||||
homepage = "http://www.abinit.org"
|
||||
url = "http://ftp.abinit.org/abinit-8.0.8b.tar.gz"
|
||||
homepage = 'http://www.abinit.org'
|
||||
url = 'http://ftp.abinit.org/abinit-8.0.8b.tar.gz'
|
||||
|
||||
version('8.2.2', '5f25250e06fdc0815c224ffd29858860')
|
||||
# Versions before 8.0.8b are not supported.
|
||||
version("8.0.8b", "abc9e303bfa7f9f43f95598f87d84d5d")
|
||||
version('8.0.8b', 'abc9e303bfa7f9f43f95598f87d84d5d')
|
||||
|
||||
variant('mpi', default=True,
|
||||
description='Builds with MPI support. Requires MPI2+')
|
||||
|
@ -71,111 +74,108 @@ class Abinit(Package):
|
|||
|
||||
# Add dependencies
|
||||
# currently one cannot forward options to virtual packages, see #1712.
|
||||
# depends_on("blas", when="~openmp")
|
||||
# depends_on("blas+openmp", when="+openmp")
|
||||
# depends_on('blas', when='~openmp')
|
||||
# depends_on('blas+openmp', when='+openmp')
|
||||
depends_on('blas')
|
||||
depends_on("lapack")
|
||||
depends_on('lapack')
|
||||
|
||||
# Require MPI2+
|
||||
depends_on("mpi@2:", when="+mpi")
|
||||
depends_on('mpi@2:', when='+mpi')
|
||||
|
||||
depends_on("scalapack", when="+scalapack+mpi")
|
||||
# depends_on("elpa", when="+elpa+mpi~openmp")
|
||||
# depends_on("elpa+openmp", when="+elpa+mpi+openmp")
|
||||
depends_on('scalapack', when='+scalapack+mpi')
|
||||
|
||||
depends_on("fftw+float", when="~openmp")
|
||||
depends_on("fftw+float+openmp", when="+openmp")
|
||||
# depends_on('elpa~openmp', when='+elpa+mpi~openmp')
|
||||
# depends_on('elpa+openmp', when='+elpa+mpi+openmp')
|
||||
|
||||
depends_on("netcdf-fortran", when="+hdf5")
|
||||
depends_on("hdf5+mpi", when='+mpi+hdf5') # required for NetCDF-4 support
|
||||
depends_on('fftw+float', when='~openmp')
|
||||
depends_on('fftw+float+openmp', when='+openmp')
|
||||
|
||||
depends_on('netcdf-fortran', when='+hdf5')
|
||||
depends_on('hdf5+mpi', when='+mpi+hdf5') # required for NetCDF-4 support
|
||||
|
||||
# pin libxc version
|
||||
depends_on("libxc@2.2.1")
|
||||
depends_on("libxc@2.2.2")
|
||||
|
||||
def validate(self, spec):
|
||||
"""
|
||||
Checks if incompatible variants have been activated at the same time
|
||||
# Cannot ask for +scalapack if it does not depend on MPI
|
||||
conflicts('+scalapack', when='~mpi')
|
||||
|
||||
:param spec: spec of the package
|
||||
:raises RuntimeError: in case of inconsistencies
|
||||
"""
|
||||
error = 'you cannot ask for \'+{variant}\' when \'+mpi\' is not active'
|
||||
# Elpa is a substitute for scalapack and needs mpi
|
||||
# conflicts('+elpa', when='~mpi')
|
||||
# conflicts('+elpa', when='+scalapack')
|
||||
|
||||
if '+scalapack' in spec and '~mpi' in spec:
|
||||
raise RuntimeError(error.format(variant='scalapack'))
|
||||
def configure_args(self):
|
||||
|
||||
if '+elpa' in spec and ('~mpi' in spec or '~scalapack' in spec):
|
||||
raise RuntimeError(error.format(variant='elpa'))
|
||||
spec = self.spec
|
||||
|
||||
def install(self, spec, prefix):
|
||||
self.validate(spec)
|
||||
|
||||
options = ['--prefix=%s' % prefix]
|
||||
options = []
|
||||
oapp = options.append
|
||||
|
||||
if '+mpi' in spec:
|
||||
# MPI version:
|
||||
# let the configure script auto-detect MPI support from mpi_prefix
|
||||
oapp("--with-mpi-prefix=%s" % spec["mpi"].prefix)
|
||||
oapp("--enable-mpi=yes")
|
||||
oapp("--enable-mpi-io=yes")
|
||||
oapp('--with-mpi-prefix={0}'.format(spec['mpi'].prefix))
|
||||
oapp('--enable-mpi=yes')
|
||||
oapp('--enable-mpi-io=yes')
|
||||
|
||||
# Activate OpenMP in Abinit Fortran code.
|
||||
if '+openmp' in spec:
|
||||
oapp('--enable-openmp=yes')
|
||||
|
||||
# BLAS/LAPACK
|
||||
# BLAS/LAPACK/SCALAPACK-ELPA
|
||||
linalg = spec['lapack'].libs + spec['blas'].libs
|
||||
if '+scalapack' in spec:
|
||||
oapp("--with-linalg-flavor=custom+scalapack")
|
||||
linalg = (spec['scalapack'].libs +
|
||||
spec['lapack'].libs + spec['blas'].libs)
|
||||
oapp('--with-linalg-flavor=custom+scalapack')
|
||||
linalg = spec['scalapack'].libs + linalg
|
||||
|
||||
# elif '+elpa' in spec:
|
||||
else:
|
||||
oapp("--with-linalg-flavor=custom")
|
||||
linalg = spec['lapack'].libs + spec['blas'].libs
|
||||
oapp('--with-linalg-flavor=custom')
|
||||
|
||||
oapp("--with-linalg-libs=%s" % linalg.ld_flags)
|
||||
oapp('--with-linalg-libs={0}'.format(linalg.ld_flags))
|
||||
|
||||
# FFTW3: use sequential or threaded version if +openmp
|
||||
fftflavor, fftlibs = "fftw3", "-lfftw3 -lfftw3f"
|
||||
fftflavor, fftlibs = 'fftw3', '-lfftw3 -lfftw3f'
|
||||
if '+openmp' in spec:
|
||||
fftflavor = "fftw3-threads"
|
||||
fftlibs = "-lfftw3_omp -lfftw3 -lfftw3f"
|
||||
fftflavor = 'fftw3-threads'
|
||||
fftlibs = '-lfftw3_omp -lfftw3 -lfftw3f'
|
||||
|
||||
options.extend([
|
||||
"--with-fft-flavor=%s" % fftflavor,
|
||||
"--with-fft-incs=-I%s" % spec["fftw"].prefix.include,
|
||||
"--with-fft-libs=-L%s %s" % (spec["fftw"].prefix.lib, fftlibs),
|
||||
'--with-fft-flavor=%s' % fftflavor,
|
||||
'--with-fft-incs=-I%s' % spec['fftw'].prefix.include,
|
||||
'--with-fft-libs=-L%s %s' % (spec['fftw'].prefix.lib, fftlibs),
|
||||
])
|
||||
oapp("--with-dft-flavor=atompaw+libxc")
|
||||
oapp('--with-dft-flavor=atompaw+libxc')
|
||||
|
||||
# LibXC library
|
||||
libxc = spec['libxc:fortran']
|
||||
options.extend([
|
||||
"with_libxc_incs=-I%s" % spec["libxc"].prefix.include,
|
||||
"with_libxc_libs=-L%s -lxcf90 -lxc" % spec["libxc"].prefix.lib,
|
||||
'with_libxc_incs={0}'.format(libxc.cppflags),
|
||||
'with_libxc_libs={0}'.format(libxc.libs.ld_flags + ' -lm')
|
||||
])
|
||||
|
||||
# Netcdf4/HDF5
|
||||
if "+hdf5" in spec:
|
||||
oapp("--with-trio-flavor=netcdf")
|
||||
if '+hdf5' in spec:
|
||||
oapp('--with-trio-flavor=netcdf')
|
||||
# Since version 8, Abinit started to use netcdf4 + hdf5 and we have
|
||||
# to link with -lhdf5_hl -lhdf5
|
||||
hdf_libs = "-L%s -lhdf5_hl -lhdf5" % spec["hdf5"].prefix.lib
|
||||
# to link with the high level HDF5 library
|
||||
hdf5 = spec['hdf5:hl']
|
||||
netcdff = spec['netcdf-fortran:shared']
|
||||
options.extend([
|
||||
"--with-netcdf-incs=-I%s" % (
|
||||
spec["netcdf-fortran"].prefix.include),
|
||||
"--with-netcdf-libs=-L%s -lnetcdff -lnetcdf %s" % (
|
||||
spec["netcdf-fortran"].prefix.lib, hdf_libs),
|
||||
'--with-netcdf-incs={0}'.format(netcdff.cppflags),
|
||||
'--with-netcdf-libs={0}'.format(
|
||||
netcdff.libs.ld_flags + ' ' + hdf5.libs.ld_flags
|
||||
),
|
||||
])
|
||||
else:
|
||||
# In Spack we do our best to avoid building any internally provided
|
||||
# dependencies, such as netcdf3 in this case.
|
||||
oapp("--with-trio-flavor=none")
|
||||
oapp('--with-trio-flavor=none')
|
||||
|
||||
configure(*options)
|
||||
make()
|
||||
return options
|
||||
|
||||
# make("check")
|
||||
# make("tests_in")
|
||||
make("install")
|
||||
def check(self):
|
||||
"""This method is called after the build phase if tests have been
|
||||
explicitly activated by user.
|
||||
"""
|
||||
make('check')
|
||||
make('tests_in')
|
||||
|
|
|
@ -70,23 +70,82 @@ class Hdf5(AutotoolsPackage):
|
|||
depends_on('szip', when='+szip')
|
||||
depends_on('zlib@1.1.2:')
|
||||
|
||||
@run_before('configure')
|
||||
def validate(self):
|
||||
"""
|
||||
Checks if incompatible variants have been activated at the same time
|
||||
# According to ./configure --help thread-safe capabilities are:
|
||||
# "Not compatible with the high-level library, Fortran, or C++ wrappers."
|
||||
# (taken from hdf5@1.10.0patch1)
|
||||
conflicts('+threadsafe', when='+cxx')
|
||||
conflicts('+threadsafe', when='+fortran')
|
||||
|
||||
:param spec: spec of the package
|
||||
:raises RuntimeError: in case of inconsistencies
|
||||
@property
|
||||
def libs(self):
|
||||
"""Hdf5 can be queried for the following parameters:
|
||||
|
||||
- "hl": high-level interface
|
||||
- "cxx": C++ APIs
|
||||
- "fortran": fortran APIs
|
||||
|
||||
:return: list of matching libraries
|
||||
"""
|
||||
query_parameters = self.spec.last_query.extra_parameters
|
||||
|
||||
shared = '+shared' in self.spec
|
||||
|
||||
# This map contains a translation from query_parameters
|
||||
# to the libraries needed
|
||||
query2libraries = {
|
||||
tuple(): ['libhdf5'],
|
||||
('cxx', 'fortran', 'hl'): [
|
||||
'libhdf5hl_fortran',
|
||||
'libhdf5_hl_cpp',
|
||||
'libhdf5_hl',
|
||||
'libhdf5_fortran',
|
||||
'libhdf5',
|
||||
],
|
||||
('cxx', 'hl'): [
|
||||
'libhdf5_hl_cpp',
|
||||
'libhdf5_hl',
|
||||
'libhdf5',
|
||||
],
|
||||
('fortran', 'hl'): [
|
||||
'libhdf5hl_fortran',
|
||||
'libhdf5_hl',
|
||||
'libhdf5_fortran',
|
||||
'libhdf5',
|
||||
],
|
||||
('hl',): [
|
||||
'libhdf5_hl',
|
||||
'libhdf5',
|
||||
],
|
||||
('cxx', 'fortran'): [
|
||||
'libhdf5_fortran',
|
||||
'libhdf5_cpp',
|
||||
'libhdf5',
|
||||
],
|
||||
('cxx',): [
|
||||
'libhdf5_cpp',
|
||||
'libhdf5',
|
||||
],
|
||||
('fortran',): [
|
||||
'libhdf5_fortran',
|
||||
'libhdf5',
|
||||
]
|
||||
}
|
||||
|
||||
# Turn the query into the appropriate key
|
||||
key = tuple(sorted(query_parameters))
|
||||
libraries = query2libraries[key]
|
||||
|
||||
return find_libraries(
|
||||
libraries, root=self.prefix, shared=shared, recurse=True
|
||||
)
|
||||
|
||||
@run_before('configure')
|
||||
def fortran_check(self):
|
||||
spec = self.spec
|
||||
if '+fortran' in spec and not self.compiler.fc:
|
||||
msg = 'cannot build a fortran variant without a fortran compiler'
|
||||
raise RuntimeError(msg)
|
||||
|
||||
if '+threadsafe' in spec and ('+cxx' in spec or '+fortran' in spec):
|
||||
msg = 'cannot use variant +threadsafe with either +cxx or +fortran'
|
||||
raise RuntimeError(msg)
|
||||
|
||||
def configure_args(self):
|
||||
spec = self.spec
|
||||
# Handle compilation after spec validation
|
||||
|
@ -156,11 +215,9 @@ def configure_args(self):
|
|||
|
||||
return ["--with-zlib=%s" % spec['zlib'].prefix] + extra_args
|
||||
|
||||
def configure(self, spec, prefix):
|
||||
# Run the default autotools package configure
|
||||
super(Hdf5, self).configure(spec, prefix)
|
||||
|
||||
if '@:1.8.14' in spec:
|
||||
@run_after('configure')
|
||||
def patch_postdeps(self):
|
||||
if '@:1.8.14' in self.spec:
|
||||
# On Ubuntu14, HDF5 1.8.12 (and maybe other versions)
|
||||
# mysteriously end up with "-l -l" in the postdeps in the
|
||||
# libtool script. Patch this by removing the spurious -l's.
|
||||
|
|
|
@ -36,6 +36,33 @@ class Libxc(Package):
|
|||
version('2.2.2', 'd9f90a0d6e36df6c1312b6422280f2ec')
|
||||
version('2.2.1', '38dc3a067524baf4f8521d5bb1cd0b8f')
|
||||
|
||||
@property
|
||||
def libs(self):
|
||||
"""Libxc can be queried for the following parameters:
|
||||
|
||||
- "static": returns the static library version of libxc
|
||||
(by default the shared version is returned)
|
||||
|
||||
:return: list of matching libraries
|
||||
"""
|
||||
query_parameters = self.spec.last_query.extra_parameters
|
||||
|
||||
libraries = ['libxc']
|
||||
|
||||
# Libxc installs both shared and static libraries.
|
||||
# If a client ask for static explicitly then return
|
||||
# the static libraries
|
||||
shared = False if 'static' in query_parameters else True
|
||||
|
||||
# Libxc has a fortran90 interface: give clients the
|
||||
# possibility to query for it
|
||||
if 'fortran' in query_parameters:
|
||||
libraries = ['libxcf90'] + libraries
|
||||
|
||||
return find_libraries(
|
||||
libraries, root=self.prefix, shared=shared, recurse=True
|
||||
)
|
||||
|
||||
def install(self, spec, prefix):
|
||||
# Optimizations for the Intel compiler, suggested by CP2K
|
||||
optflags = '-O2'
|
||||
|
|
|
@ -35,3 +35,16 @@ class NetcdfFortran(AutotoolsPackage):
|
|||
version('4.4.3', 'bfd4ae23a34635b273d3eb0d91cbde9e')
|
||||
|
||||
depends_on('netcdf')
|
||||
|
||||
@property
|
||||
def libs(self):
|
||||
libraries = ['libnetcdff']
|
||||
|
||||
# This package installs both shared and static libraries. Permit
|
||||
# clients to query which one they want.
|
||||
query_parameters = self.spec.last_query.extra_parameters
|
||||
shared = 'shared' in query_parameters
|
||||
|
||||
return find_libraries(
|
||||
libraries, root=self.prefix, shared=shared, recurse=True
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue