402 lines
17 KiB
Python
402 lines
17 KiB
Python
# 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)
|
|
|
|
import os
|
|
|
|
import llnl.util.filesystem as fs
|
|
import llnl.util.tty as tty
|
|
|
|
from spack.package import *
|
|
|
|
|
|
class Octopus(AutotoolsPackage, CudaPackage):
|
|
"""A real-space finite-difference (time-dependent) density-functional
|
|
theory code."""
|
|
|
|
homepage = "https://octopus-code.org/"
|
|
url = "https://octopus-code.org/download/6.0/octopus-6.0.tar.gz"
|
|
git = "https://gitlab.com/octopus-code/octopus"
|
|
|
|
maintainers("fangohr", "RemiLacroix-IDRIS", "iamashwin99")
|
|
|
|
license("Apache-2.0")
|
|
|
|
version("14.0", sha256="3cf6ef571ff97cc2c226016815d2ac4aa1e00ae3fb0cc693e0aff5620b80373e")
|
|
version("13.0", sha256="b4d0fd496c31a9c4aa4677360e631765049373131e61f396b00048235057aeb1")
|
|
version("12.2", sha256="e919e07703696eadb4ba59352d7a2678a9191b4586cb9da538661615e765a5a2")
|
|
version("12.1", sha256="e2214e958f1e9631dbe6bf020c39f1fe4d71ab0b6118ea9bd8dc38f6d7a7959a")
|
|
version("12.0", sha256="70beaf08573d394a766f10346a708219b355ad725642126065d12596afbc0dcc")
|
|
version("11.4", sha256="73bb872bff8165ddd8efc5b891f767cb3fe575b5a4b518416c834450a4492da7")
|
|
version("11.3", sha256="0c98417071b5e38ba6cbdd409adf917837c387a010e321c0a7f94d9bd9478930")
|
|
version("11.1", sha256="d943cc2419ca409dda7459b7622987029f2af89984d0d5f39a6b464c3fc266da")
|
|
version("10.5", sha256="deb92e3491b0c6ac5736960d075b44cab466f528b69715ed44968ecfe2953ec4")
|
|
version("10.4", sha256="4de9dc6f5815a45e43320e4abc7ef3e501e34bc327441376ea20ca1a992bdb72")
|
|
version("10.3", sha256="4633490e21593b51b60a8391b8aa0ed17fa52a3a0030630de123b67a41f88b33")
|
|
version("10.2", sha256="393e2ba7b18af1b736ad6deb339ba0cef18c6417671da7a6f1fcc3a5d8f7586b")
|
|
version("10.1", sha256="b6a660a99ed593c1d491e2d11cfff9ce87f0d80d527d9ff47fd983533d45adc6")
|
|
version("10.0", sha256="ccf62200e3f37911bfff6d127ebe74220996e9c09383a10b1420c81d931dcf23")
|
|
version("7.3", sha256="ad843d49d4beeed63e8b9a2ca6bfb2f4c5a421f13a4f66dc7b02f6d6a5c4d742")
|
|
version("6.0", sha256="4a802ee86c1e06846aa7fa317bd2216c6170871632c9e03d020d7970a08a8198")
|
|
version("5.0.1", sha256="3423049729e03f25512b1b315d9d62691cd0a6bd2722c7373a61d51bfbee14e0")
|
|
|
|
version("develop", branch="main")
|
|
|
|
variant("mpi", default=True, description="Build with MPI support")
|
|
variant("scalapack", default=False, when="+mpi", description="Compile with Scalapack")
|
|
variant("berkeleygw", default=False, description="Compile with BerkeleyGW")
|
|
variant("metis", default=False, description="Compile with METIS")
|
|
variant("parmetis", default=False, when="+mpi", description="Compile with ParMETIS")
|
|
variant("netcdf", default=False, description="Compile with Netcdf")
|
|
variant(
|
|
"sparskit",
|
|
default=False,
|
|
description="Compile with Sparskit - A Basic Tool Kit for Sparse Matrix Computations",
|
|
)
|
|
variant("arpack", default=False, description="Compile with ARPACK")
|
|
variant("cgal", default=False, description="Compile with CGAL library support")
|
|
variant("pfft", default=False, when="+mpi", description="Compile with PFFT")
|
|
variant(
|
|
"nfft",
|
|
default=False,
|
|
description="Compile with NFFT - Nonequispaced Fast Fourier Transform library",
|
|
)
|
|
# poke here refers to https://gitlab.e-cam2020.eu/esl/poke
|
|
# variant('poke', default=False,
|
|
# description='Compile with poke (not available in spack yet)')
|
|
variant("python", default=False, description="Activates Python support")
|
|
variant("likwid", default=False, description="Compile with likwid")
|
|
variant("libvdwxc", default=False, description="Compile with libvdwxc")
|
|
variant("libyaml", default=False, description="Compile with libyaml")
|
|
variant("elpa", default=False, description="Compile with ELPA")
|
|
variant("etsf-io", default=False, description="Compile with etsf-io")
|
|
variant("nlopt", default=False, description="Compile with nlopt")
|
|
variant(
|
|
"pnfft",
|
|
default=False,
|
|
when="+pfft",
|
|
description="Compile with PNFFT - Parallel Nonequispaced FFT library",
|
|
)
|
|
variant("debug", default=False, description="Compile with debug flags")
|
|
|
|
depends_on("autoconf", type="build", when="@develop")
|
|
depends_on("automake", type="build", when="@develop")
|
|
depends_on("libtool", type="build", when="@develop")
|
|
depends_on("m4", type="build", when="@develop")
|
|
depends_on("mpi", when="+mpi")
|
|
|
|
depends_on("blas")
|
|
depends_on("gsl@1.9:")
|
|
depends_on("lapack")
|
|
|
|
# The library of exchange and correlation functionals.
|
|
depends_on("libxc@2:2", when="@:5")
|
|
depends_on("libxc@2:3", when="@6:7")
|
|
depends_on("libxc@2:4", when="@8:9")
|
|
depends_on("libxc@5.1.0:", when="@10:")
|
|
depends_on("libxc@5.1.0:", when="@develop")
|
|
depends_on("netcdf-fortran", when="+netcdf") # NetCDF fortran lib without mpi variant
|
|
with when("+mpi"): # list all the parallel dependencies
|
|
depends_on("fftw@3:+mpi+openmp", when="@8:9") # FFT library
|
|
depends_on("fftw-api@3:", when="@10:")
|
|
depends_on("fftw+mpi+openmp", when="^[virtuals=fftw-api] fftw")
|
|
depends_on("libvdwxc+mpi", when="+libvdwxc")
|
|
depends_on("arpack-ng+mpi", when="+arpack")
|
|
depends_on("elpa+mpi", when="+elpa")
|
|
depends_on("netcdf-c+mpi", when="+netcdf") # Link dependency of NetCDF fortran lib
|
|
with when("+berkeleygw"):
|
|
# From octopus@14:, upstream switched support from BerkeleyGW@2.1 to @3.0:
|
|
# see https://gitlab.com/octopus-code/octopus/-/merge_requests/2257
|
|
# BerkeleyGW 2.1 is the last supported version until octopus@14
|
|
depends_on("berkeleygw@3:+mpi", when="@14:")
|
|
depends_on("berkeleygw@2.1+mpi", when="@:13")
|
|
|
|
with when("~mpi"): # list all the serial dependencies
|
|
depends_on("fftw@3:+openmp~mpi", when="@8:9") # FFT library
|
|
depends_on("fftw-api@3:", when="@10:")
|
|
depends_on("fftw~mpi+openmp", when="^[virtuals=fftw-api] fftw")
|
|
depends_on("libvdwxc~mpi", when="+libvdwxc")
|
|
depends_on("arpack-ng~mpi", when="+arpack")
|
|
depends_on("elpa~mpi", when="+elpa")
|
|
depends_on("netcdf-c~~mpi", when="+netcdf") # Link dependency of NetCDF fortran lib
|
|
with when("+berkeleygw"):
|
|
depends_on("berkeleygw@3:~~mpi", when="@14:")
|
|
depends_on("berkeleygw@2.1~~mpi", when="@:13")
|
|
|
|
depends_on("etsf-io", when="+etsf-io")
|
|
depends_on("py-numpy", when="+python")
|
|
depends_on("py-mpi4py", when="+python")
|
|
depends_on("metis@5:+int64", when="+metis")
|
|
depends_on("parmetis+int64", when="+parmetis")
|
|
depends_on("scalapack", when="+scalapack")
|
|
depends_on("sparskit", when="+sparskit")
|
|
depends_on("cgal", when="+cgal")
|
|
depends_on("pfft", when="+pfft")
|
|
depends_on("nfft@3.2.4", when="+nfft")
|
|
depends_on("likwid", when="+likwid")
|
|
depends_on("libyaml", when="+libyaml")
|
|
depends_on("pnfft", when="+pnfft")
|
|
depends_on("nlopt", when="+nlopt")
|
|
|
|
# optional dependencies:
|
|
# TODO: etsf-io, sparskit,
|
|
# feast, libfm, pfft, isf, pnfft, poke
|
|
|
|
def configure_args(self):
|
|
spec = self.spec
|
|
lapack = spec["lapack"].libs
|
|
blas = spec["blas"].libs
|
|
args = []
|
|
args.extend(
|
|
[
|
|
"--prefix=%s" % prefix,
|
|
"--with-blas=%s" % blas.ld_flags,
|
|
"--with-lapack=%s" % lapack.ld_flags,
|
|
"--with-gsl-prefix=%s" % spec["gsl"].prefix,
|
|
"--with-libxc-prefix=%s" % spec["libxc"].prefix,
|
|
"--enable-openmp",
|
|
]
|
|
)
|
|
if "+mpi" in self.spec: # we build with MPI
|
|
args.extend(
|
|
[
|
|
"--enable-mpi",
|
|
"CC=%s" % self.spec["mpi"].mpicc,
|
|
"FC=%s" % self.spec["mpi"].mpifc,
|
|
]
|
|
)
|
|
else:
|
|
args.extend(["CC=%s" % self.compiler.cc, "FC=%s" % self.compiler.fc])
|
|
|
|
if "^fftw" in spec:
|
|
args.append("--with-fftw-prefix=%s" % spec["fftw"].prefix)
|
|
elif spec["fftw-api"].name in INTEL_MATH_LIBRARIES:
|
|
# As of version 10.0, Octopus depends on fftw-api instead
|
|
# of FFTW. If FFTW is not in the dependency tree, then
|
|
# it ought to be MKL as it is currently the only providers
|
|
# available for fftw-api.
|
|
args.append("FCFLAGS_FFTW=-I%s" % spec["mkl"].prefix.include.fftw)
|
|
else:
|
|
# To be foolproof, fail with a proper error message
|
|
# if neither FFTW nor MKL are in the dependency tree.
|
|
tty.die(
|
|
'Unsupported "fftw-api" provider, '
|
|
"currently only FFTW and MKL are supported.\n"
|
|
"Please report this issue on Spack's repository."
|
|
)
|
|
if "+metis" in spec:
|
|
args.append("--with-metis-prefix=%s" % spec["metis"].prefix)
|
|
if "+parmetis" in spec:
|
|
args.append("--with-parmetis-prefix=%s" % spec["parmetis"].prefix)
|
|
if "+netcdf" in spec:
|
|
args.extend(
|
|
[
|
|
"--with-netcdf-prefix=%s" % spec["netcdf-fortran"].prefix,
|
|
"--with-netcdf-include=%s" % spec["netcdf-fortran"].prefix.include,
|
|
]
|
|
)
|
|
if "+arpack" in spec:
|
|
arpack_libs = spec["arpack-ng"].libs.joined()
|
|
args.append("--with-arpack={0}".format(arpack_libs))
|
|
if "+mpi" in spec["arpack-ng"]:
|
|
args.append("--with-parpack={0}".format(arpack_libs))
|
|
|
|
if "+scalapack" in spec:
|
|
args.extend(
|
|
[
|
|
f"--with-blacs={spec['scalapack'].libs.ld_flags}",
|
|
f"--with-scalapack={spec['scalapack'].libs.ld_flags}",
|
|
]
|
|
)
|
|
|
|
if "+cgal" in spec:
|
|
# Boost is a dependency of CGAL, and is not picked up by the configure script
|
|
# unless specified explicitly with `--with-boost` option.
|
|
args.append("--with-cgal-prefix=%s" % spec["cgal"].prefix)
|
|
args.append("--with-boost=%s" % spec["boost"].prefix)
|
|
|
|
if "+likwid" in spec:
|
|
args.append("--with-likwid-prefix=%s" % spec["likwid"].prefix)
|
|
|
|
if "+pfft" in spec:
|
|
args.append("--with-pfft-prefix=%s" % spec["pfft"].prefix)
|
|
|
|
if "+nfft" in spec:
|
|
args.append("--with-nfft=%s" % spec["nfft"].prefix)
|
|
|
|
# if '+poke' in spec:
|
|
# args.extend([
|
|
# '--with-poke-prefix=%s' % spec['poke'].prefix,
|
|
# ])
|
|
if "+pnfft" in spec:
|
|
args.append("--with-pnfft-prefix=%s" % spec["pnfft"].prefix)
|
|
|
|
if "+libvdwxc" in spec:
|
|
args.append("--with-libvdwxc-prefix=%s" % spec["libvdwxc"].prefix)
|
|
|
|
if "+libyaml" in spec:
|
|
args.append("--with-libyaml-prefix=%s" % spec["libyaml"].prefix)
|
|
|
|
if "+elpa" in spec:
|
|
args.append("--with-elpa-prefix=%s" % spec["elpa"].prefix)
|
|
|
|
if "+nlopt" in spec:
|
|
args.append("--with-nlopt-prefix=%s" % spec["nlopt"].prefix)
|
|
|
|
if "+cuda" in spec:
|
|
args.append("--enable-cuda")
|
|
|
|
if "+python" in spec:
|
|
args.append("--enable-python")
|
|
|
|
if "+sparskit" in spec:
|
|
args.append(
|
|
"--with-sparskit=%s" % os.path.join(self.spec["sparskit"].prefix.lib, "libskit.a")
|
|
)
|
|
if "+etsf-io" in spec:
|
|
args.append("--with-etsf-io-prefix=%s" % spec["etsf-io"].prefix)
|
|
# --with-pfft-prefix=${prefix} --with-mpifftw-prefix=${prefix}
|
|
# --with-berkeleygw-prefix=${prefix}
|
|
if "+berkeleygw" in spec:
|
|
args.append("--with-berkeleygw-prefix=%s" % spec["berkeleygw"].prefix)
|
|
|
|
# When preprocessor expands macros (i.e. CFLAGS) defined as quoted
|
|
# strings the result may be > 132 chars and is terminated.
|
|
# This will look to a compiler as an Unterminated character constant
|
|
# and produce Line truncated errors. To overcome this, add flags to
|
|
# let compiler know that the entire line is meaningful.
|
|
# TODO: For the lack of better approach, assume that clang is mixed
|
|
# with GNU fortran.
|
|
if spec.satisfies("%apple-clang") or spec.satisfies("%clang") or spec.satisfies("%gcc"):
|
|
# In case of GCC version 10, we will have errors because of
|
|
# argument mismatching. Need to provide a flag to turn this into a
|
|
# warning and build sucessfully
|
|
# We can disable variable tracking at assignments introduced in GCC10
|
|
# for debug variant to decrease compile time.
|
|
|
|
# Set optimization level for all flags
|
|
opt_level = "-O2"
|
|
fcflags = f"FCFLAGS={opt_level} -ffree-line-length-none"
|
|
cxxflags = f"CXXFLAGS={opt_level}"
|
|
cflags = f"CFLAGS={opt_level}"
|
|
|
|
# Add extra flags for gcc 10 or higher
|
|
gcc10_extra = (
|
|
"-fallow-argument-mismatch -fallow-invalid-boz"
|
|
if spec.satisfies("%gcc@10:")
|
|
else ""
|
|
)
|
|
# Add debug flag if needed
|
|
if spec.satisfies("+debug"):
|
|
fcflags += " -g"
|
|
cxxflags += " -g"
|
|
cflags += " -g"
|
|
gcc10_extra += (
|
|
"-fno-var-tracking-assignments" if spec.satisfies("%gcc@10:") else ""
|
|
)
|
|
|
|
args.append(f"{fcflags} {gcc10_extra}")
|
|
args.append(f"{cxxflags} {gcc10_extra}")
|
|
args.append(f"{cflags} {gcc10_extra}")
|
|
|
|
return args
|
|
|
|
@run_after("install")
|
|
@on_package_attributes(run_tests=True)
|
|
def smoke_tests_after_install(self):
|
|
"""Function stub to run tests after install if desired
|
|
(for example through `spack install --test=root octopus`)
|
|
"""
|
|
self.smoke_tests()
|
|
|
|
def test(self):
|
|
"""Entry point for smoke tests run through `spack test run octopus`."""
|
|
self.smoke_tests()
|
|
|
|
def smoke_tests(self):
|
|
"""Actual smoke tests for Octopus."""
|
|
#
|
|
# run "octopus --version"
|
|
#
|
|
exe = join_path(self.spec.prefix.bin, "octopus")
|
|
options = ["--version"]
|
|
purpose = "Check octopus can execute (--version)"
|
|
# Example output:
|
|
#
|
|
# spack-v0.17.2$ octopus --version
|
|
# octopus 11.3 (git commit )
|
|
expected = ["octopus "]
|
|
|
|
self.run_test(
|
|
exe,
|
|
options=options,
|
|
expected=expected,
|
|
status=[0],
|
|
installed=False,
|
|
purpose=purpose,
|
|
skip_missing=False,
|
|
)
|
|
|
|
# Octopus expects a file with name `inp` in the current working
|
|
# directory to read configuration information for a simulation run from
|
|
# that file. We copy the relevant configuration file in a dedicated
|
|
# subfolder for each test.
|
|
#
|
|
# As we like to be able to run these tests also with the
|
|
# `spack install --test=root` command, we cannot rely on
|
|
# self.test_suite.current_test_data_dir, and need to copy the test
|
|
# input files manually (see below).
|
|
|
|
#
|
|
# run recipe example
|
|
#
|
|
|
|
expected = [
|
|
"Running octopus",
|
|
"CalculationMode = recipe",
|
|
"DISCLAIMER: The authors do not " "guarantee that the implementation",
|
|
"recipe leads to an edible dish, " 'for it is clearly "system-dependent".',
|
|
"Calculation ended on",
|
|
]
|
|
options = []
|
|
purpose = "Run Octopus recipe example"
|
|
with working_dir("example-recipe", create=True):
|
|
print("Current working directory (in example-recipe)")
|
|
fs.copy(join_path(os.path.dirname(__file__), "test", "recipe.inp"), "inp")
|
|
self.run_test(
|
|
exe,
|
|
options=options,
|
|
expected=expected,
|
|
status=[0],
|
|
installed=False,
|
|
purpose=purpose,
|
|
skip_missing=False,
|
|
)
|
|
|
|
#
|
|
# run He example
|
|
#
|
|
expected = [
|
|
"Running octopus",
|
|
"Info: Starting calculation mode.",
|
|
"CalculationMode = gs",
|
|
"""Species "helium" is a user-defined potential.""",
|
|
"Info: Writing states.",
|
|
"Calculation ended on",
|
|
]
|
|
options = []
|
|
purpose = "Run tiny calculation for He"
|
|
with working_dir("example-he", create=True):
|
|
print("Current working directory (in example-he)")
|
|
fs.copy(join_path(os.path.dirname(__file__), "test", "he.inp"), "inp")
|
|
self.run_test(
|
|
exe,
|
|
options=options,
|
|
expected=expected,
|
|
status=[0],
|
|
installed=False,
|
|
purpose=purpose,
|
|
skip_missing=False,
|
|
)
|