1e68ebbecSBarry Smith#!/usr/bin/env python 2e68ebbecSBarry Smith 3e68ebbecSBarry Smith""" 465a891e7SLisandro DalcinPETSc: Portable, Extensible Toolkit for Scientific Computation 565a891e7SLisandro Dalcin============================================================== 665a891e7SLisandro Dalcin 765a891e7SLisandro DalcinThe Portable, Extensible Toolkit for Scientific Computation (PETSc), 865a891e7SLisandro Dalcinis a suite of data structures and routines for the scalable (parallel) 965a891e7SLisandro Dalcinsolution of scientific applications modeled by partial differential 1065a891e7SLisandro Dalcinequations. It employs the Message Passing Interface (MPI) standard for 1165a891e7SLisandro Dalcinall message-passing communication. 12922ada92SLisandro Dalcin 1393b33a5aSLisandro Dalcin.. note:: 1493b33a5aSLisandro Dalcin 1593b33a5aSLisandro Dalcin To install ``PETSc`` and ``petsc4py`` (``mpi4py`` is optional 1693b33a5aSLisandro Dalcin but highly recommended) use:: 1793b33a5aSLisandro Dalcin 1893b33a5aSLisandro Dalcin $ pip install numpy mpi4py 1993b33a5aSLisandro Dalcin $ pip install petsc petsc4py 2093b33a5aSLisandro Dalcin 21922ada92SLisandro Dalcin.. tip:: 22922ada92SLisandro Dalcin 2393b33a5aSLisandro Dalcin You can also install the in-development versions with:: 24922ada92SLisandro Dalcin 2593b33a5aSLisandro Dalcin $ pip install Cython numpy mpi4py 2693b33a5aSLisandro Dalcin $ pip install --no-deps https://bitbucket.org/petsc/petsc/get/master.tar.gz 2793b33a5aSLisandro Dalcin $ pip install --no-deps https://bitbucket.org/petsc/petsc4py/get/master.tar.gz 28ca62002aSBarry Smith 29e68ebbecSBarry Smith""" 30e68ebbecSBarry Smith 3165a891e7SLisandro Dalcinimport sys, os 3296fd8cd7SLisandro Dalcinfrom setuptools import setup 3396fd8cd7SLisandro Dalcinfrom setuptools.command.install import install as _install 34cb58ab5bSLisandro Dalcinfrom distutils.util import get_platform, split_quoted 35b88f8b63SLisandro Dalcinfrom distutils.spawn import find_executable 3665a891e7SLisandro Dalcinfrom distutils import log 3712c1d45bSMatthew G Knepley 3865a891e7SLisandro Dalcininit_py = """\ 39a32381aeSLisandro Dalcin# Author: PETSc Team 40a597b971SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov 4165a891e7SLisandro Dalcin 4265a891e7SLisandro Dalcindef get_petsc_dir(): 4365a891e7SLisandro Dalcin import os 4465a891e7SLisandro Dalcin return os.path.dirname(__file__) 4565a891e7SLisandro Dalcin 46a32381aeSLisandro Dalcindef get_config(): 47a32381aeSLisandro Dalcin conf = {} 489fb7a39fSLisandro Dalcin conf['PETSC_DIR'] = get_petsc_dir() 49a32381aeSLisandro Dalcin return conf 5065a891e7SLisandro Dalcin""" 5165a891e7SLisandro Dalcin 5259e0f383SLisandro Dalcinmetadata = { 5359e0f383SLisandro Dalcin 'provides' : ['petsc'], 5496fd8cd7SLisandro Dalcin 'zip_safe' : False, 5559e0f383SLisandro Dalcin} 5659e0f383SLisandro Dalcin 5715075023SLisandro DalcinCONFIGURE_OPTIONS = [] 5815075023SLisandro Dalcin 5965a891e7SLisandro Dalcindef bootstrap(): 60cb58ab5bSLisandro Dalcin # Set PETSC_DIR and PETSC_ARCH 6165a891e7SLisandro Dalcin PETSC_DIR = os.path.abspath(os.getcwd()) 6296fd8cd7SLisandro Dalcin PETSC_ARCH = 'arch-python-' + get_platform() 6365a891e7SLisandro Dalcin os.environ['PETSC_DIR'] = PETSC_DIR 6465a891e7SLisandro Dalcin os.environ['PETSC_ARCH'] = PETSC_ARCH 6565a891e7SLisandro Dalcin sys.path.insert(0, os.path.join(PETSC_DIR, 'config')) 66*af0996ceSBarry Smith sys.path.insert(0, os.path.join(PETSC_DIR, 'lib','petsc','conf')) 6759e0f383SLisandro Dalcin # Generate package __init__.py file 689fb7a39fSLisandro Dalcin from distutils.dir_util import mkpath 699fb7a39fSLisandro Dalcin pkgdir = os.path.join('config', 'pypi') 700ddf2052SLisandro Dalcin if not os.path.exists(pkgdir): mkpath(pkgdir) 719fb7a39fSLisandro Dalcin pkgfile = os.path.join(pkgdir, '__init__.py') 7296fd8cd7SLisandro Dalcin fh = open(pkgfile, 'w') 73922ada92SLisandro Dalcin fh.write(init_py) 74922ada92SLisandro Dalcin fh.close() 7515075023SLisandro Dalcin # Configure options 7615075023SLisandro Dalcin options = os.environ.get('PETSC_CONFIGURE_OPTIONS', '') 7715075023SLisandro Dalcin CONFIGURE_OPTIONS.extend(split_quoted(options)) 7815075023SLisandro Dalcin if '--with-mpi=0' not in CONFIGURE_OPTIONS: 7959e0f383SLisandro Dalcin # Simple-minded lookup for MPI and mpi4py 8059e0f383SLisandro Dalcin mpi4py = mpicc = None 8159e0f383SLisandro Dalcin try: 8259e0f383SLisandro Dalcin import mpi4py 8359e0f383SLisandro Dalcin conf = mpi4py.get_config() 8459e0f383SLisandro Dalcin mpicc = conf.get('mpicc') 8559e0f383SLisandro Dalcin except ImportError: # mpi4py is not installed 86922ada92SLisandro Dalcin mpi4py = None 8715075023SLisandro Dalcin mpicc = (os.environ.get('MPICC') or 8815075023SLisandro Dalcin find_executable('mpicc')) 891b095333SLisandro Dalcin except AttributeError: # mpi4py is too old 9059e0f383SLisandro Dalcin pass 91922ada92SLisandro Dalcin if not mpi4py and mpicc: 92922ada92SLisandro Dalcin metadata['install_requires'] = ['mpi4py>=1.2.2'] 9365a891e7SLisandro Dalcin 9496fd8cd7SLisandro Dalcindef config(prefix, dry_run=False): 9565a891e7SLisandro Dalcin log.info('PETSc: configure') 9665a891e7SLisandro Dalcin options = [ 9796fd8cd7SLisandro Dalcin '--prefix=' + prefix, 9865a891e7SLisandro Dalcin 'PETSC_ARCH='+os.environ['PETSC_ARCH'], 99cb58ab5bSLisandro Dalcin '--with-shared-libraries=1', 10011035aebSLisandro Dalcin '--with-debugging=0', 101922ada92SLisandro Dalcin '--with-c2html=0', # not needed 10265a891e7SLisandro Dalcin ] 10315075023SLisandro Dalcin if '--with-fc=0' in CONFIGURE_OPTIONS: 10415075023SLisandro Dalcin options.append('--with-sowing=0') 10515075023SLisandro Dalcin if '--with-mpi=0' not in CONFIGURE_OPTIONS: 10659e0f383SLisandro Dalcin try: 10759e0f383SLisandro Dalcin import mpi4py 10859e0f383SLisandro Dalcin conf = mpi4py.get_config() 10959e0f383SLisandro Dalcin mpicc = conf.get('mpicc') 110cb58ab5bSLisandro Dalcin mpicxx = conf.get('mpicxx') 111cb58ab5bSLisandro Dalcin mpif90 = conf.get('mpif90') 11259e0f383SLisandro Dalcin except (ImportError, AttributeError): 11359e0f383SLisandro Dalcin mpicc = os.environ.get('MPICC') or find_executable('mpicc') 114cb58ab5bSLisandro Dalcin mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx') 115cb58ab5bSLisandro Dalcin mpif90 = os.environ.get('MPIF90') or find_executable('mpif90') 11659e0f383SLisandro Dalcin if mpicc: 11759e0f383SLisandro Dalcin options.append('--with-cc='+mpicc) 11815075023SLisandro Dalcin if '--with-cxx=0' not in CONFIGURE_OPTIONS: 119cb58ab5bSLisandro Dalcin if mpicxx: 120cb58ab5bSLisandro Dalcin options.append('--with-cxx='+mpicxx) 12193b33a5aSLisandro Dalcin else: 12293b33a5aSLisandro Dalcin options.append('--with-cxx=0') 12315075023SLisandro Dalcin if '--with-fc=0' not in CONFIGURE_OPTIONS: 124cb58ab5bSLisandro Dalcin if mpif90: 125cb58ab5bSLisandro Dalcin options.append('--with-fc='+mpif90) 12659e0f383SLisandro Dalcin else: 12793b33a5aSLisandro Dalcin options.append('--with-fc=0') 12893b33a5aSLisandro Dalcin options.append('--with-sowing=0') 12993b33a5aSLisandro Dalcin else: 13059e0f383SLisandro Dalcin options.append('--with-mpi=0') 13115075023SLisandro Dalcin options.extend(CONFIGURE_OPTIONS) 13215075023SLisandro Dalcin # 133cb58ab5bSLisandro Dalcin log.info('configure options:') 134cb58ab5bSLisandro Dalcin for opt in options: 135cb58ab5bSLisandro Dalcin log.info(' '*4 + opt) 13659e0f383SLisandro Dalcin # Run PETSc configure 137cb58ab5bSLisandro Dalcin if dry_run: return 13896fd8cd7SLisandro Dalcin use_config_py = True 13996fd8cd7SLisandro Dalcin if use_config_py: 140e68ebbecSBarry Smith import configure 14165a891e7SLisandro Dalcin configure.petsc_configure(options) 142e68ebbecSBarry Smith import logger 143e68ebbecSBarry Smith logger.Logger.defaultLog = None 14496fd8cd7SLisandro Dalcin else: 14596fd8cd7SLisandro Dalcin command = ['./configure'] + options 14696fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 14796fd8cd7SLisandro Dalcin if status != 0: raise RuntimeError(status) 14812c1d45bSMatthew G Knepley 14965a891e7SLisandro Dalcindef build(dry_run=False): 15065a891e7SLisandro Dalcin log.info('PETSc: build') 151367c215cSLisandro Dalcin # Run PETSc build 152cb58ab5bSLisandro Dalcin if dry_run: return 153367c215cSLisandro Dalcin use_builder_py = False 154367c215cSLisandro Dalcin if use_builder_py: 155e68ebbecSBarry Smith import builder 156e68ebbecSBarry Smith builder.PETScMaker().run() 157105e34d4SBarry Smith import logger 158105e34d4SBarry Smith logger.Logger.defaultLog = None 159367c215cSLisandro Dalcin else: 160367c215cSLisandro Dalcin make = find_executable('make') 16196fd8cd7SLisandro Dalcin command = [make, 'all'] 16296fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 163367c215cSLisandro Dalcin if status != 0: raise RuntimeError(status) 164e68ebbecSBarry Smith 16596fd8cd7SLisandro Dalcindef install(dest_dir, dry_run=False): 16665a891e7SLisandro Dalcin log.info('PETSc: install') 16765a891e7SLisandro Dalcin options = [ 16865a891e7SLisandro Dalcin '--destDir=' + dest_dir, 16965a891e7SLisandro Dalcin ] 170cb58ab5bSLisandro Dalcin log.info('install options:') 171cb58ab5bSLisandro Dalcin for opt in options: 172cb58ab5bSLisandro Dalcin log.info(' '*4 + opt) 17359e0f383SLisandro Dalcin # Run PETSc installer 174cb58ab5bSLisandro Dalcin if dry_run: return 175367c215cSLisandro Dalcin use_install_py = True 176367c215cSLisandro Dalcin if use_install_py: 177105e34d4SBarry Smith import install 17865a891e7SLisandro Dalcin install.Installer(options).run() 17965a891e7SLisandro Dalcin import logger 18065a891e7SLisandro Dalcin logger.Logger.defaultLog = None 181367c215cSLisandro Dalcin else: 182367c215cSLisandro Dalcin make = find_executable('make') 18396fd8cd7SLisandro Dalcin command = [make, 'install', 'DESTDIR='+dest_dir] 18496fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 185367c215cSLisandro Dalcin if status != 0: raise RuntimeError(status) 18699468c80SLisandro Dalcin 18796fd8cd7SLisandro Dalcinclass context(object): 18899468c80SLisandro Dalcin def __init__(self): 18999468c80SLisandro Dalcin self.sys_argv = sys.argv[:] 19099468c80SLisandro Dalcin self.wdir = os.getcwd() 19199468c80SLisandro Dalcin def enter(self): 19299468c80SLisandro Dalcin del sys.argv[1:] 19399468c80SLisandro Dalcin pdir = os.environ['PETSC_DIR'] 19499468c80SLisandro Dalcin os.chdir(pdir) 19599468c80SLisandro Dalcin return self 19699468c80SLisandro Dalcin def exit(self): 19799468c80SLisandro Dalcin sys.argv[:] = self.sys_argv 19899468c80SLisandro Dalcin os.chdir(self.wdir) 199105e34d4SBarry Smith 20065a891e7SLisandro Dalcinclass cmd_install(_install): 20165a891e7SLisandro Dalcin 20241716173SLisandro Dalcin def initialize_options(self): 20341716173SLisandro Dalcin _install.initialize_options(self) 20441716173SLisandro Dalcin self.optimize = 1 20541716173SLisandro Dalcin 20689031a3cSLisandro Dalcin def finalize_options(self): 20789031a3cSLisandro Dalcin _install.finalize_options(self) 20889031a3cSLisandro Dalcin self.install_lib = self.install_platlib 20989031a3cSLisandro Dalcin self.install_libbase = self.install_lib 21089031a3cSLisandro Dalcin 21165a891e7SLisandro Dalcin def run(self): 21289031a3cSLisandro Dalcin root_dir = os.path.abspath(self.install_lib) 21396fd8cd7SLisandro Dalcin dest_dir = prefix = os.path.join(root_dir, 'petsc') 21499468c80SLisandro Dalcin # 21599468c80SLisandro Dalcin ctx = context().enter() 21665a891e7SLisandro Dalcin try: 21796fd8cd7SLisandro Dalcin config(prefix, self.dry_run) 21896fd8cd7SLisandro Dalcin build(self.dry_run) 21996fd8cd7SLisandro Dalcin install(dest_dir, self.dry_run) 22065a891e7SLisandro Dalcin finally: 22199468c80SLisandro Dalcin ctx.exit() 22296fd8cd7SLisandro Dalcin # 22396fd8cd7SLisandro Dalcin self.outputs = [] 22496fd8cd7SLisandro Dalcin for dirpath, _, filenames in os.walk(dest_dir): 22596fd8cd7SLisandro Dalcin for fn in filenames: 22696fd8cd7SLisandro Dalcin self.outputs.append(os.path.join(dirpath, fn)) 22796fd8cd7SLisandro Dalcin # 22896fd8cd7SLisandro Dalcin _install.run(self) 22965a891e7SLisandro Dalcin 23096fd8cd7SLisandro Dalcin def get_outputs(self): 23196fd8cd7SLisandro Dalcin outputs = getattr(self, 'outputs', []) 23296fd8cd7SLisandro Dalcin outputs += _install.get_outputs(self) 23396fd8cd7SLisandro Dalcin return outputs 234a32381aeSLisandro Dalcin 23565a891e7SLisandro Dalcindef version(): 2367d04d9c9SLisandro Dalcin import re 2377d04d9c9SLisandro Dalcin version_re = { 2387d04d9c9SLisandro Dalcin 'major' : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"), 2397d04d9c9SLisandro Dalcin 'minor' : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"), 2407d04d9c9SLisandro Dalcin 'micro' : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"), 2417d04d9c9SLisandro Dalcin 'patch' : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"), 2427d04d9c9SLisandro Dalcin 'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"), 2437d04d9c9SLisandro Dalcin } 2447d04d9c9SLisandro Dalcin petscversion_h = os.path.join('include','petscversion.h') 24596fd8cd7SLisandro Dalcin data = open(petscversion_h, 'r').read() 2467d04d9c9SLisandro Dalcin major = int(version_re['major'].search(data).groups()[0]) 2477d04d9c9SLisandro Dalcin minor = int(version_re['minor'].search(data).groups()[0]) 2487d04d9c9SLisandro Dalcin micro = int(version_re['micro'].search(data).groups()[0]) 2497d04d9c9SLisandro Dalcin patch = int(version_re['patch'].search(data).groups()[0]) 2507d04d9c9SLisandro Dalcin release = int(version_re['release'].search(data).groups()[0]) 2517d04d9c9SLisandro Dalcin if release: 2527d04d9c9SLisandro Dalcin v = "%d.%d" % (major, minor) 2537d04d9c9SLisandro Dalcin if micro > 0: 2547d04d9c9SLisandro Dalcin v += ".%d" % micro 255247a1238SLisandro Dalcin #if patch > 0: 256247a1238SLisandro Dalcin # v += ".post%d" % patch 2577d04d9c9SLisandro Dalcin else: 25861a717f9SLisandro Dalcin v = "%d.%d.dev%d" % (major, minor+1, 0) 2597d04d9c9SLisandro Dalcin return v 26059e0f383SLisandro Dalcin 26165a891e7SLisandro Dalcindef tarball(): 26250f36069SLisandro Dalcin VERSION = version() 26350f36069SLisandro Dalcin if '.dev' in VERSION: 264a32381aeSLisandro Dalcin return None 2657d562c6eSLisandro Dalcin bits = VERSION.split('.') 2667d562c6eSLisandro Dalcin if len(bits) == 2: bits.append('0') 267247a1238SLisandro Dalcin PETSC_VERSION = '.'.join(bits[:3]) 26850f36069SLisandro Dalcin return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/' 269a9157d91SLisandro Dalcin 'petsc-lite-%s.tar.gz#egg=petsc-%s' % (PETSC_VERSION, VERSION)) 27065a891e7SLisandro Dalcin 27165a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3] 27265a891e7SLisandro Dalcinclassifiers = """ 27396fd8cd7SLisandro DalcinDevelopment Status :: 5 - Production/Stable 27465a891e7SLisandro DalcinIntended Audience :: Developers 27565a891e7SLisandro DalcinIntended Audience :: Science/Research 27696fd8cd7SLisandro DalcinLicense :: OSI Approved :: BSD License 27796fd8cd7SLisandro DalcinOperating System :: POSIX 27865a891e7SLisandro DalcinProgramming Language :: C 27965a891e7SLisandro DalcinProgramming Language :: C++ 28065a891e7SLisandro DalcinProgramming Language :: Fortran 28165a891e7SLisandro DalcinProgramming Language :: Python 28265a891e7SLisandro DalcinTopic :: Scientific/Engineering 28365a891e7SLisandro DalcinTopic :: Software Development :: Libraries 28465a891e7SLisandro Dalcin""" 28565a891e7SLisandro Dalcin 28665a891e7SLisandro Dalcinbootstrap() 28765a891e7SLisandro Dalcinsetup(name='petsc', 28865a891e7SLisandro Dalcin version=version(), 28965a891e7SLisandro Dalcin description=description.pop(0), 29065a891e7SLisandro Dalcin long_description='\n'.join(description), 29165a891e7SLisandro Dalcin classifiers= classifiers.split('\n')[1:-1], 29265a891e7SLisandro Dalcin keywords = ['PETSc', 'MPI'], 29365a891e7SLisandro Dalcin platforms=['POSIX'], 29465a891e7SLisandro Dalcin license='PETSc', 29565a891e7SLisandro Dalcin 29665a891e7SLisandro Dalcin url='http://www.mcs.anl.gov/petsc/', 29765a891e7SLisandro Dalcin download_url=tarball(), 29865a891e7SLisandro Dalcin 29965a891e7SLisandro Dalcin author='PETSc Team', 30099468c80SLisandro Dalcin author_email='petsc-maint@mcs.anl.gov', 30165a891e7SLisandro Dalcin maintainer='Lisandro Dalcin', 30265a891e7SLisandro Dalcin maintainer_email='dalcinl@gmail.com', 30365a891e7SLisandro Dalcin 30465a891e7SLisandro Dalcin packages = ['petsc'], 3059fb7a39fSLisandro Dalcin package_dir = {'petsc': 'config/pypi'}, 30696fd8cd7SLisandro Dalcin cmdclass={'install': cmd_install}, 30759e0f383SLisandro Dalcin **metadata) 308