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) | ||||
|         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 | ||||
|         ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user