1import os 2import sys 3import numpy 4import platform 5import sysconfig 6 7try: 8 from setuptools import setup, Extension 9 use_setuptools = True 10 print("setuptools is used.") 11except ImportError: 12 from distutils.core import setup, Extension 13 use_setuptools = False 14 print("distutils is used.") 15 16try: 17 from setuptools_scm import get_version 18except ImportError: 19 git_num = None 20 21if 'setuptools_scm' in sys.modules.keys(): 22 try: 23 git_ver = get_version() 24 git_num = int(git_ver.split('.')[3].split('+')[0].replace("dev", "")) 25 except: 26 git_num = None 27 28include_dirs_numpy = [numpy.get_include()] 29extra_link_args = [] 30# Workaround Python issue 21121 31config_var = sysconfig.get_config_var("CFLAGS") 32if (config_var is not None and 33 "-Werror=declaration-after-statement" in config_var): 34 os.environ['CFLAGS'] = config_var.replace( 35 "-Werror=declaration-after-statement", "") 36 37extra_compile_args = ['-fopenmp', ] 38include_dirs = ['c', ] + include_dirs_numpy 39define_macros = [] 40 41extra_link_args_lapacke = [] 42include_dirs_lapacke = [] 43 44 45use_mkl = False 46# C macro definitions: 47# - MULTITHREADED_BLAS 48# This deactivates OpenMP multithread harmonic phonon calculation, 49# since inside each phonon calculation, zheev is called. 50# When using multithread BLAS, this macro has to be set and 51# by this all phonons on q-points should be calculated in series. 52# - MKL_LAPACKE: 53# This sets definitions and functions needed when using MKL lapacke. 54# Phono3py complex values are handled based on those provided by Netlib 55# lapacke. However MKL lapacke doesn't provide some macros and functions 56# that provided Netlib. This macro defines those used in phono3py among them. 57if os.path.isfile("setup_mkl.py"): 58 # This supposes that MKL multithread BLAS is used. 59 # This is invoked when setup_mkl.py exists on the current directory. 60 61 print("MKL LAPACKE is to be used.") 62 print("Use of icc is assumed (CC='icc').") 63 64 from setup_mkl import mkl_extra_link_args_lapacke, mkl_include_dirs_lapacke 65 66 #### Examples of setup_mkl.py #### 67 # For 2015 68 # intel_root = "/opt/intel/composer_xe_2015.7.235" 69 # mkl_root = "%s/mkl" % intel_root 70 # compiler_root = "%s/compiler" % intel_root 71 # 72 # For 2016 73 # intel_root = "/opt/intel/parallel_studio_xe_2016" 74 # mkl_root = "%s/mkl" % intel_root 75 # compiler_root = "%s" % intel_root 76 # 77 # For both 78 # mkl_extra_link_args_lapacke = ['-L%s/lib/intel64' % mkl_root, 79 # '-lmkl_rt'] 80 # mkl_extra_link_args_lapacke += ['-L%s/lib/intel64' % compiler_root, 81 # '-lsvml', 82 # '-liomp5', 83 # '-limf', 84 # '-lpthread'] 85 # mkl_include_dirs_lapacke = ["%s/include" % mkl_root] 86 87 use_mkl = True 88 extra_link_args_lapacke += mkl_extra_link_args_lapacke 89 include_dirs_lapacke += mkl_include_dirs_lapacke 90 91 if use_setuptools: 92 extra_compile_args += ['-DMKL_LAPACKE', 93 '-DMULTITHREADED_BLAS'] 94 else: 95 define_macros += [('MKL_LAPACKE', None), 96 ('MULTITHREADED_BLAS', None)] 97elif os.path.isfile("libopenblas.py"): 98 # This supposes that multithread openBLAS is used. 99 # This is invoked when libopenblas.py exists on the current directory. 100 101 #### Example of libopenblas.py #### 102 # extra_link_args_lapacke += ['-lopenblas'] 103 104 from libopenblas import extra_link_args_lapacke, include_dirs_lapacke 105 include_dirs_lapacke += [] 106 if use_setuptools: 107 extra_compile_args += ['-DMULTITHREADED_BLAS'] 108 else: 109 define_macros += [('MULTITHREADED_BLAS', None)] 110elif (platform.system() == 'Darwin' and 111 os.path.isfile('/opt/local/lib/libopenblas.a')): 112 # This supposes lapacke with single-thread openBLAS provided by MacPort is 113 # used. 114 # % sudo port install gcc6 115 # % sudo port select --set gcc mp-gcc 116 # % sudo port install OpenBLAS +gcc6 117 extra_link_args_lapacke += ['/opt/local/lib/libopenblas.a'] 118 include_dirs_lapacke += ['/opt/local/include'] 119elif ('CONDA_PREFIX' in os.environ and 120 (os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'], 121 'lib', 'liblapacke.dylib')) or 122 os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'], 123 'lib', 'liblapacke.so')))): 124 # This is for the system prepared with conda openblas. 125 extra_link_args_lapacke += ['-llapacke'] 126 include_dirs_lapacke += [ 127 os.path.join(os.environ['CONDA_PREFIX'], 'include'), ] 128 if os.path.isfile(os.path.join(os.environ['CONDA_PREFIX'], 129 'include', 'mkl.h')): 130 use_mkl = True 131 if use_setuptools: 132 extra_compile_args += ['-DMKL_LAPACKE', 133 '-DMULTITHREADED_BLAS'] 134 else: 135 define_macros += [('MKL_LAPACKE', None), 136 ('MULTITHREADED_BLAS', None)] 137 else: 138 if use_setuptools: 139 extra_compile_args += ['-DMULTITHREADED_BLAS'] 140 else: 141 define_macros += [('MULTITHREADED_BLAS', None)] 142elif os.path.isfile('/usr/lib/liblapacke.so'): 143 # This supposes that lapacke with single-thread BLAS is installed on 144 # system. 145 extra_link_args_lapacke += ['-llapacke', '-llapack', '-lblas'] 146 include_dirs_lapacke += [] 147else: 148 # Here is the default lapacke linkage setting. 149 # Please modify according to your system environment. 150 # Without using multithreaded BLAS, DMULTITHREADED_BLAS is better to be 151 # removed to activate OpenMP multithreading harmonic phonon calculation, 152 # but this is not mandatory. 153 # 154 # The below supposes that lapacke with multithread openblas is used. 155 # Even if using single-thread BLAS and deactivating OpenMP 156 # multithreading for harmonic phonon calculation, the total performance 157 # decrease is considered marginal. 158 # 159 # For conda: Try installing with dynamic link library of openblas by 160 # % conda install numpy scipy h5py pyyaml matplotlib openblas libgfortran 161 extra_link_args_lapacke += ['-lopenblas', '-lgfortran'] 162 if 'CONDA_PREFIX' in os.environ: 163 include_dirs_lapacke += [ 164 os.path.join(os.environ['CONDA_PREFIX'], 'include'), ] 165 if use_setuptools: 166 extra_compile_args += ['-DMULTITHREADED_BLAS'] 167 else: 168 define_macros += [('MULTITHREADED_BLAS', None)] 169 170cc = None 171lib_omp = None 172if 'CC' in os.environ: 173 if 'clang' in os.environ['CC']: 174 cc = 'clang' 175 if not use_mkl: 176 lib_omp = '-lomp' 177 # lib_omp = '-liomp5' 178 if 'gcc' in os.environ['CC'] or 'gnu-cc' in os.environ['CC']: 179 cc = 'gcc' 180if cc == 'gcc' or cc is None: 181 lib_omp = '-lgomp' 182 183 if 'CC' in os.environ and 'gcc-' in os.environ['CC']: 184 # For macOS & homebrew gcc: 185 # Using conda's gcc is more recommended though. Suppose using 186 # homebrew gcc whereas conda is used as general environment. 187 # This is to avoid linking conda libgomp that is incompatible 188 # with homebrew gcc. 189 try: 190 v = int(os.environ['CC'].split('-')[1]) 191 except ValueError: 192 pass 193 else: 194 ary = [os.sep, "usr", "local", "opt", "gcc@%d" % v, "lib", "gcc", 195 "%d" % v, "libgomp.a"] 196 libgomp_a = os.path.join(*ary) 197 if os.path.isfile(libgomp_a): 198 lib_omp = libgomp_a 199 200if lib_omp: 201 extra_link_args.append(lib_omp) 202 203## Uncomment below to measure reciprocal_to_normal_squared_openmp performance 204# define_macros += [('MEASURE_R2N', None)] 205 206extra_link_args += extra_link_args_lapacke 207include_dirs += include_dirs_lapacke 208 209print("extra_link_args", extra_link_args) 210sources_phono3py = ['c/_phono3py.c', 211 'c/collision_matrix.c', 212 'c/fc3.c', 213 'c/imag_self_energy_with_g.c', 214 'c/interaction.c', 215 'c/isotope.c', 216 'c/kgrid.c', 217 'c/kpoint.c', 218 'c/lapack_wrapper.c', 219 'c/mathfunc.c', 220 'c/phono3py.c', 221 'c/phonoc_utils.c', 222 'c/pp_collision.c', 223 'c/real_self_energy.c', 224 'c/real_to_reciprocal.c', 225 'c/reciprocal_to_normal.c', 226 'c/tetrahedron_method.c', 227 'c/triplet.c', 228 'c/triplet_iw.c', 229 'c/triplet_kpoint.c'] 230extension_phono3py = Extension( 231 'phono3py._phono3py', 232 include_dirs=include_dirs, 233 extra_compile_args=extra_compile_args, 234 extra_link_args=extra_link_args, 235 define_macros=define_macros, 236 sources=sources_phono3py) 237 238sources_phononmod = ['c/_phononmod.c', 239 'c/dynmat.c', 240 'c/lapack_wrapper.c', 241 'c/phonon.c', 242 'c/phononmod.c'] 243extension_phononmod = Extension( 244 'phono3py._phononmod', 245 include_dirs=include_dirs, 246 extra_compile_args=extra_compile_args, 247 extra_link_args=extra_link_args, 248 sources=sources_phononmod) 249 250sources_lapackepy = ['c/_lapackepy.c', 251 'c/lapack_wrapper.c'] 252extension_lapackepy = Extension( 253 'phono3py._lapackepy', 254 extra_compile_args=extra_compile_args, 255 extra_link_args=extra_link_args, 256 include_dirs=include_dirs, 257 sources=sources_lapackepy) 258 259packages_phono3py = ['phono3py', 260 'phono3py.cui', 261 'phono3py.interface', 262 'phono3py.other', 263 'phono3py.phonon', 264 'phono3py.phonon3', 265 'phono3py.sscha'] 266scripts_phono3py = ['scripts/phono3py', 267 'scripts/phono3py-load', 268 'scripts/phono3py-kaccum', 269 'scripts/phono3py-kdeplot', 270 'scripts/phono3py-coleigplot'] 271 272######################## 273# _lapackepy extension # 274######################## 275 276if __name__ == '__main__': 277 version_nums = [None, None, None] 278 with open("phono3py/version.py") as w: 279 for line in w: 280 if "__version__" in line: 281 for i, num in enumerate( 282 line.split()[2].strip('\"').split('.')): 283 version_nums[i] = num 284 break 285 286 # To deploy to pypi by travis-CI 287 if os.path.isfile("__nanoversion__.txt"): 288 nanoversion = 0 289 with open('__nanoversion__.txt') as nv: 290 try: 291 for line in nv: 292 nanoversion = int(line.strip()) 293 break 294 except ValueError: 295 nanoversion = 0 296 if nanoversion != 0: 297 version_nums.append(nanoversion) 298 elif git_num: 299 version_nums.append(git_num) 300 301 if None in version_nums: 302 print("Failed to get version number in setup.py.") 303 raise 304 305 version = ".".join(["%s" % n for n in version_nums[:3]]) 306 if len(version_nums) > 3: 307 version += "-%d" % version_nums[3] 308 309 if use_setuptools: 310 setup(name='phono3py', 311 version=version, 312 description='This is the phono3py module.', 313 author='Atsushi Togo', 314 author_email='atz.togo@gmail.com', 315 url='http://phonopy.github.io/phono3py/', 316 packages=packages_phono3py, 317 install_requires=['numpy', 'scipy', 'PyYAML', 'matplotlib', 318 'h5py', 'spglib', 'phonopy>=2.9.3,<2.10'], 319 provides=['phono3py'], 320 scripts=scripts_phono3py, 321 ext_modules=[extension_phono3py, 322 extension_lapackepy, 323 extension_phononmod]) 324 else: 325 setup(name='phono3py', 326 version=version, 327 description='This is the phono3py module.', 328 author='Atsushi Togo', 329 author_email='atz.togo@gmail.com', 330 url='http://phonopy.github.io/phono3py/', 331 packages=packages_phono3py, 332 requires=['numpy', 'scipy', 'PyYAML', 'matplotlib', 'h5py', 333 'phonopy', 'spglib'], 334 provides=['phono3py'], 335 scripts=scripts_phono3py, 336 ext_modules=[extension_phono3py, 337 extension_lapackepy, 338 extension_phononmod]) 339