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