summaryrefslogblamecommitdiff
path: root/var/spack/repos/builtin/packages/berkeleygw/package.py
blob: 28895615a6ed6820df43d7705fadbcf7570ef2e9 (plain) (tree)
1
2
3
4
5
6
                                                                         



                                                                         
                           









                                                                                 
                                  
 

                
                                                                                  




                                                                                         
                                                                                  

                                                                                         
     

              
                                                                                  



                                                                                         



                                                                                    
                                                                        
                                                                            
                                                                            





                                                                             
                                  
                                        

                                                       

                                                  



























                                                                                                   
 





                                                                      
                                   
 

                                                                                           
                                                                   




                                                               




                                                          

                                                                        

                                      



                                                                                                   
 
                                          
                                               
                                                                                  

                                                     

                                                           

                                      

                                                   



                                                                             

                       

                                                          




                                                              
 
















                                                                                             

                                  


                      

                                     
 

                                                                  

                                     
                                                    
 


                                                                 

                      
                            
                                   
                              
                                     
                                                    
 





                                                              
 
                                                       
                                                                               


                      






                                                                               
                          





                                                                                 
                                                             









                                                                              
                                                           


                                    
                                                                                    





                                                         
                                                     







                                                                                   
                                                           


                                    
                               

                                                
                                                     








                                                                                         
             















                                                                                  
                 
                                

                                                     


                                                                                    
 

                                                                                  
 
                                                             
 
                                       

                                    
                                              
# 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)

from spack.package import *


class Berkeleygw(MakefilePackage):
    """BerkeleyGW is a many-body perturbation theory code for excited states,
    using the GW method and the GW plus Bethe-Salpeter equation (GW-BSE) method
    to solve respectively for quasiparticle excitations and optical properties of
    materials."""

    homepage = "https://berkeleygw.org"

    maintainers("migueldiascosta")

    version(
        "3.0.1",
        sha256="7d8c2cc1ee679afb48efbdd676689d4d537226b50e13a049dbcb052aaaf3654f",
        url="https://berkeley.box.com/shared/static/m1dgnhiemo47lhxczrn6si71bwxoxor8.gz",
        expand=False,
    )
    version(
        "3.0",
        sha256="ab411acead5e979fd42b8d298dbb0a12ce152e7be9eee0bb87e9e5a06a638e2a",
        url="https://berkeley.box.com/shared/static/lp6hj4kxr459l5a6t05qfuzl2ucyo03q.gz",
        expand=False,
    )
    version(
        "2.1",
        sha256="31f3b643dd937350c3866338321d675d4a1b1f54c730b43ad74ae67e75a9e6f2",
        url="https://berkeley.box.com/shared/static/ze3azi5vlyw7hpwvl9i5f82kaiid6g0x.gz",
        expand=False,
    )

    # For parallel computing support, enable +mpi. It uses MPI and ScaLAPACK
    # which are inter-dependent in the berkeleygw code(they need each other):
    # https://github.com/spack/spack/pull/33948#issuecomment-1323805817
    variant("mpi", default=True, description="Build with MPI and ScaLAPACK support")
    variant("elpa", default=True, description="Build with ELPA support")
    variant("python", default=True, description="Build with Python support")
    variant("openmp", default=True, description="Build with OpenMP support")
    variant("hdf5", default=True, description="Builds with HDF5 support")
    variant("debug", default=False, description="Builds with DEBUG flag")
    variant("verbose", default=False, description="Builds with VERBOSE flag")

    depends_on("blas")
    depends_on("lapack")
    depends_on("mpi", when="+mpi")
    depends_on("scalapack", when="+mpi")
    depends_on("hdf5+fortran+hl", when="+hdf5~mpi")
    depends_on("hdf5+fortran+hl+mpi", when="+hdf5+mpi")
    depends_on("elpa+openmp", when="+elpa+openmp")
    depends_on("elpa~openmp", when="+elpa~openmp")

    depends_on("fftw-api@3")
    with when("+openmp"):
        depends_on("acfl threads=openmp", when="^[virtuals=fftw-api] acfl")
        depends_on("amdfftw+openmp", when="^[virtuals=fftw-api] amdfftw")
        depends_on("armpl-gcc threads=openmp", when="^[virtuals=fftw-api] armpl-gcc")
        depends_on("cray-fftw+openmp", when="^[virtuals=fftw-api] cray-fftw")
        depends_on("fftw+openmp", when="^[virtuals=fftw-api] fftw")
        depends_on("fujitsu-fftw+openmp", when="^[virtuals=fftw-api] fujitsu-fftw")
        depends_on("intel-mkl threads=openmp", when="^[virtuals=fftw-api] intel-mkl")
        depends_on("intel-oneapi-mkl threads=openmp", when="^[virtuals=fftw-api] intel-oneapi-mkl")
        depends_on(
            "intel-parallel-studio threads=openmp",
            when="^[virtuals=fftw-api] intel-parallel-studio",
        )

    with when("~openmp"):
        depends_on("acfl threads=none", when="^[virtuals=fftw-api] acfl")
        depends_on("amdfftw~openmp", when="^[virtuals=fftw-api] amdfftw")
        depends_on("armpl-gcc threads=none", when="^[virtuals=fftw-api] armpl-gcc")
        depends_on("cray-fftw~openmp", when="^[virtuals=fftw-api] cray-fftw")
        depends_on("fftw~openmp", when="^[virtuals=fftw-api] fftw")
        depends_on("fujitsu-fftw~openmp", when="^[virtuals=fftw-api] fujitsu-fftw")
        depends_on("intel-mkl threads=none", when="^[virtuals=fftw-api] intel-mkl")
        depends_on("intel-oneapi-mkl threads=none", when="^[virtuals=fftw-api] intel-oneapi-mkl")
        depends_on(
            "intel-parallel-studio threads=none", when="^[virtuals=fftw-api] intel-parallel-studio"
        )

    # in order to run the installed python scripts
    depends_on("python", type=("build", "run"), when="+python")
    depends_on("py-numpy", type=("build", "run"), when="+python")
    depends_on("py-setuptools", type=("build", "run"), when="+python")
    depends_on("py-h5py", type=("build", "run"), when="+hdf5+python")

    depends_on("perl", type="test")

    conflicts("+elpa", when="~mpi", msg="elpa is a parallel library and needs MPI support")

    # Force openmp propagation on some providers of blas / fftw-api
    with when("+openmp"):
        depends_on("fftw+openmp", when="^fftw")
        depends_on("amdfftw+openmp", when="^amdfftw")
        depends_on("openblas threads=openmp", when="^openblas")
        depends_on("amdblis threads=openmp", when="^amdblis")

    parallel = False

    def edit(self, spec, prefix):
        # archive is a tar file, despite the .gz expension
        tar = which("tar")
        tar("-x", "-f", self.stage.archive_file, "--strip-components=1")

        # get generic arch.mk template
        if "+mpi" in spec:
            copy(join_path(self.stage.source_path, "config", "generic.mpi.linux.mk"), "arch.mk")
        else:
            copy(join_path(self.stage.source_path, "config", "generic.serial.linux.mk"), "arch.mk")

        if self.version == Version("2.1"):
            # don't try to install missing file
            filter_file("install manual.html", "#install manual.html", "Makefile")

        # don't rebuild in the install and test steps
        filter_file("install: all", "install:", "Makefile")
        filter_file("check: all", "check:", "Makefile")

        # use parallelization in tests
        filter_file(
            r"cd testsuite \&\& \$\(MAKE\) check$",
            "cd testsuite && export BGW_TEST_MPI_NPROCS=2 OMP_NUM_THREADS=2 \
             SAVETESTDIRS=yes TEMPDIRPATH=%s && \
             $(MAKE) check-parallel"
            % join_path(self.build_directory, "tmp"),
            "Makefile",
        )

        # remove stack ulimit in order to run openmp tests
        filter_file(
            r"function run_testsuite\(\) {",
            "function run_testsuite() {\nulimit -s unlimited",
            "testsuite/run_testsuite.sh",
        )

        # slightly raise tolerance of some tests
        si_epm_tests = ["Si", "Si_cplx_spin"]
        if self.version >= Version("3.0"):
            si_epm_tests.append("Si_hdf5")
        for test in si_epm_tests:
            filter_file(
                "Precision : 6e-15",
                "Precision : 7e-15",
                join_path("testsuite", "Si-EPM", test + ".test"),
            )
        for test in ["Si_subspace", "Si_subspace_cplx", "Si_subspace_cplx_spin"]:
            filter_file(
                "Precision : 6e-15",
                "Precision : 7e-15",
                join_path("testsuite", "Si-EPM_subspace", test + ".test"),
            )
        filter_file("Precision : 8e-15", "Precision : 9e-15", "testsuite/GaAs-EPM/GaAs.test")

    def build(self, spec, prefix):
        buildopts = []
        paraflags = []

        if "+mpi" in spec:
            paraflags.append("-DMPI")

        # We need to copy fflags in case we append to it (#34019):
        fflags = spec.compiler_flags["fflags"][:]
        if "+openmp" in spec:
            paraflags.append("-DOMP")
            fflags.append(self.compiler.openmp_flag)

        if "+mpi" in spec:
            buildopts.append("C_PARAFLAG=-DPARA")
            buildopts.append("PARAFLAG=%s" % " ".join(paraflags))

        debugflag = ""
        if "+debug" in spec:
            debugflag += "-DDEBUG "
        if "+verbose" in spec:
            debugflag += "-DVERBOSE "
        buildopts.append("DEBUGFLAG=%s" % debugflag)

        if "+mpi" in spec:
            buildopts.append("LINK=%s" % spec["mpi"].mpifc)
            buildopts.append("C_LINK=%s" % spec["mpi"].mpicxx)
        else:
            buildopts.append("LINK=%s" % spack_fc)
            buildopts.append("C_LINK=%s" % spack_cxx)

        buildopts.append("FOPTS=%s" % " ".join(fflags))
        buildopts.append("C_OPTS=%s" % " ".join(spec.compiler_flags["cflags"]))

        mathflags = []

        mathflags.append("-DUSEFFTW3")
        buildopts.append("FFTWINCLUDE=%s" % spec["fftw-api"].prefix.include)
        fftwspec = spec["fftw-api:openmp" if "+openmp" in spec else "fftw-api"]
        buildopts.append("FFTWLIB=%s" % fftwspec.libs.ld_flags)

        buildopts.append("LAPACKLIB=%s" % spec["lapack"].libs.ld_flags)

        if "+mpi" in spec:
            mathflags.append("-DUSESCALAPACK")
            buildopts.append("SCALAPACKLIB=%s" % spec["scalapack"].libs.ld_flags)

        if spec.satisfies("%intel"):
            buildopts.append("COMPFLAG=-DINTEL")
            buildopts.append("MOD_OPT=-module ")
            buildopts.append("FCPP=cpp -C -P -ffreestanding")
            if "+mpi" in spec:
                buildopts.append("F90free=%s -free" % spec["mpi"].mpifc)
                buildopts.append("C_COMP=%s" % spec["mpi"].mpicc)
                buildopts.append("CC_COMP=%s" % spec["mpi"].mpicxx)
                buildopts.append("BLACSDIR=%s" % spec["scalapack"].libs)
                buildopts.append("BLACS=%s" % spec["scalapack"].libs.ld_flags)
            else:
                buildopts.append("F90free=%s -free" % spack_fc)
                buildopts.append("C_COMP=%s" % spack_cc)
                buildopts.append("CC_COMP=%s" % spack_cxx)
            buildopts.append("FOPTS=%s" % " ".join(fflags))
        elif spec.satisfies("%gcc"):
            c_flags = "-std=c99"
            cxx_flags = "-std=c++0x"
            f90_flags = "-ffree-form -ffree-line-length-none -fno-second-underscore"
            if spec.satisfies("%gcc@10:"):
                c_flags += " -fcommon"
                cxx_flags += " -fcommon"
                f90_flags += " -fallow-argument-mismatch"
            buildopts.append("COMPFLAG=-DGNU")
            buildopts.append("MOD_OPT=-J ")
            buildopts.append("FCPP=cpp -C -nostdinc")
            if "+mpi" in spec:
                buildopts.append("F90free=%s %s" % (spec["mpi"].mpifc, f90_flags))
                buildopts.append("C_COMP=%s %s" % (spec["mpi"].mpicc, c_flags))
                buildopts.append("CC_COMP=%s %s" % (spec["mpi"].mpicxx, cxx_flags))
            else:
                buildopts.append("F90free=%s %s" % (spack_fc, f90_flags))
                buildopts.append("C_COMP=%s %s" % (spack_cc, c_flags))
                buildopts.append("CC_COMP=%s %s" % (spack_cxx, cxx_flags))
            buildopts.append("FOPTS=%s" % " ".join(fflags))
        elif spec.satisfies("%fj"):
            c_flags = "-std=c99"
            cxx_flags = "-std=c++0x"
            f90_flags = "-Free"
            buildopts.append("COMPFLAG=")
            buildopts.append("MOD_OPT=-module ")
            buildopts.append("FCPP=cpp -C -nostdinc")
            if "+mpi" in spec:
                buildopts.append("F90free=%s %s" % (spec["mpi"].mpifc, f90_flags))
                buildopts.append("C_COMP=%s %s" % (spec["mpi"].mpicc, c_flags))
                buildopts.append("CC_COMP=%s %s" % (spec["mpi"].mpicxx, cxx_flags))
            else:
                buildopts.append("F90free=%s %s" % (spack_fc, f90_flags))
                buildopts.append("C_COMP=%s %s" % (spack_cc, c_flags))
                buildopts.append("CC_COMP=%s %s" % (spack_cxx, cxx_flags))
                buildopts.append("FOPTS=-Kfast -Knotemparraystack %s" % " ".join(fflags))
        else:
            raise InstallError(
                "Spack does not yet have support for building "
                "BerkeleyGW with compiler %s" % spec.compiler
            )

        if "+hdf5" in spec:
            mathflags.append("-DHDF5")
            buildopts.append("HDF5INCLUDE=%s" % spec["hdf5"].prefix.include)
            buildopts.append("HDF5LIB=%s" % spec["hdf5:hl,fortran"].libs.ld_flags)

        if "+elpa" in spec:
            mathflags.append("-DUSEELPA")
            elpa = spec["elpa"]

            if "+openmp" in spec:
                elpa_suffix = "_openmp"
            else:
                elpa_suffix = ""

            elpa_incdir = elpa.headers.directories[0]
            elpa_libs = join_path(
                elpa.libs.directories[0], "libelpa%s.%s" % (elpa_suffix, dso_suffix)
            )

            buildopts.append("ELPALIB=%s" % elpa_libs)
            buildopts.append("ELPAINCLUDE=%s" % join_path(elpa_incdir, "modules"))

        buildopts.append("MATHFLAG=%s" % " ".join(mathflags))

        make("all-flavors", *buildopts)

    def install(self, spec, prefix):
        make("install", "INSTDIR=%s" % prefix)