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 32*96fd8cd7SLisandro Dalcinfrom setuptools import setup 33*96fd8cd7SLisandro 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'], 54*96fd8cd7SLisandro Dalcin 'zip_safe' : False, 5559e0f383SLisandro Dalcin} 5659e0f383SLisandro Dalcin 5765a891e7SLisandro Dalcindef bootstrap(): 58cb58ab5bSLisandro Dalcin # Set PETSC_DIR and PETSC_ARCH 5965a891e7SLisandro Dalcin PETSC_DIR = os.path.abspath(os.getcwd()) 60*96fd8cd7SLisandro Dalcin PETSC_ARCH = 'arch-python-' + get_platform() 6165a891e7SLisandro Dalcin os.environ['PETSC_DIR'] = PETSC_DIR 6265a891e7SLisandro Dalcin os.environ['PETSC_ARCH'] = PETSC_ARCH 6365a891e7SLisandro Dalcin sys.path.insert(0, os.path.join(PETSC_DIR, 'config')) 64*96fd8cd7SLisandro Dalcin sys.path.insert(0, os.path.join(PETSC_DIR, 'lib','petsc-conf')) 6559e0f383SLisandro Dalcin # Generate package __init__.py file 669fb7a39fSLisandro Dalcin from distutils.dir_util import mkpath 679fb7a39fSLisandro Dalcin pkgdir = os.path.join('config', 'pypi') 680ddf2052SLisandro Dalcin if not os.path.exists(pkgdir): mkpath(pkgdir) 699fb7a39fSLisandro Dalcin pkgfile = os.path.join(pkgdir, '__init__.py') 70*96fd8cd7SLisandro Dalcin fh = open(pkgfile, 'w') 71922ada92SLisandro Dalcin fh.write(init_py) 72922ada92SLisandro Dalcin fh.close() 7359e0f383SLisandro Dalcin # Simple-minded lookup for MPI and mpi4py 7459e0f383SLisandro Dalcin mpi4py = mpicc = None 7559e0f383SLisandro Dalcin try: 7659e0f383SLisandro Dalcin import mpi4py 7759e0f383SLisandro Dalcin conf = mpi4py.get_config() 7859e0f383SLisandro Dalcin mpicc = conf.get('mpicc') 7959e0f383SLisandro Dalcin except ImportError: # mpi4py is not installed 80922ada92SLisandro Dalcin mpi4py = None 8159e0f383SLisandro Dalcin mpicc = os.environ.get('MPICC') or find_executable('mpicc') 821b095333SLisandro Dalcin except AttributeError: # mpi4py is too old 8359e0f383SLisandro Dalcin pass 84922ada92SLisandro Dalcin if not mpi4py and mpicc: 85922ada92SLisandro Dalcin metadata['install_requires'] = ['mpi4py>=1.2.2'] 8665a891e7SLisandro Dalcin 87*96fd8cd7SLisandro Dalcindef config(prefix, dry_run=False): 8865a891e7SLisandro Dalcin log.info('PETSc: configure') 8965a891e7SLisandro Dalcin options = [ 90*96fd8cd7SLisandro Dalcin '--prefix=' + prefix, 9165a891e7SLisandro Dalcin 'PETSC_ARCH='+os.environ['PETSC_ARCH'], 92cb58ab5bSLisandro Dalcin '--with-shared-libraries=1', 9311035aebSLisandro Dalcin '--with-debugging=0', 94922ada92SLisandro Dalcin '--with-c2html=0', # not needed 9565a891e7SLisandro Dalcin ] 9659e0f383SLisandro Dalcin # MPI 9759e0f383SLisandro Dalcin try: 9859e0f383SLisandro Dalcin import mpi4py 9959e0f383SLisandro Dalcin conf = mpi4py.get_config() 10059e0f383SLisandro Dalcin mpicc = conf.get('mpicc') 101cb58ab5bSLisandro Dalcin mpicxx = conf.get('mpicxx') 102cb58ab5bSLisandro Dalcin mpif90 = conf.get('mpif90') 10359e0f383SLisandro Dalcin except (ImportError, AttributeError): 10459e0f383SLisandro Dalcin mpicc = os.environ.get('MPICC') or find_executable('mpicc') 105cb58ab5bSLisandro Dalcin mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx') 106cb58ab5bSLisandro Dalcin mpif90 = os.environ.get('MPIF90') or find_executable('mpif90') 10759e0f383SLisandro Dalcin if mpicc: 10859e0f383SLisandro Dalcin options.append('--with-cc='+mpicc) 109cb58ab5bSLisandro Dalcin if mpicxx: 110cb58ab5bSLisandro Dalcin options.append('--with-cxx='+mpicxx) 11193b33a5aSLisandro Dalcin else: 11293b33a5aSLisandro Dalcin options.append('--with-cxx=0') 113cb58ab5bSLisandro Dalcin if mpif90: 114cb58ab5bSLisandro Dalcin options.append('--with-fc='+mpif90) 11559e0f383SLisandro Dalcin else: 11693b33a5aSLisandro Dalcin options.append('--with-fc=0') 11793b33a5aSLisandro Dalcin options.append('--with-sowing=0') 11893b33a5aSLisandro Dalcin else: 11959e0f383SLisandro Dalcin options.append('--with-mpi=0') 120cb58ab5bSLisandro Dalcin # Extra configure options 121cb58ab5bSLisandro Dalcin config_opts = os.environ.get('PETSC_CONFIGURE_OPTIONS', '') 122cb58ab5bSLisandro Dalcin config_opts = split_quoted(config_opts) 123cb58ab5bSLisandro Dalcin options.extend(config_opts) 124cb58ab5bSLisandro Dalcin log.info('configure options:') 125cb58ab5bSLisandro Dalcin for opt in options: 126cb58ab5bSLisandro Dalcin log.info(' '*4 + opt) 12759e0f383SLisandro Dalcin # Run PETSc configure 128cb58ab5bSLisandro Dalcin if dry_run: return 129*96fd8cd7SLisandro Dalcin use_config_py = True 130*96fd8cd7SLisandro Dalcin if use_config_py: 131e68ebbecSBarry Smith import configure 13265a891e7SLisandro Dalcin configure.petsc_configure(options) 133e68ebbecSBarry Smith import logger 134e68ebbecSBarry Smith logger.Logger.defaultLog = None 135*96fd8cd7SLisandro Dalcin else: 136*96fd8cd7SLisandro Dalcin command = ['./configure'] + options 137*96fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 138*96fd8cd7SLisandro Dalcin if status != 0: raise RuntimeError(status) 13912c1d45bSMatthew G Knepley 14065a891e7SLisandro Dalcindef build(dry_run=False): 14165a891e7SLisandro Dalcin log.info('PETSc: build') 142367c215cSLisandro Dalcin # Run PETSc build 143cb58ab5bSLisandro Dalcin if dry_run: return 144367c215cSLisandro Dalcin use_builder_py = False 145367c215cSLisandro Dalcin if use_builder_py: 146e68ebbecSBarry Smith import builder 147e68ebbecSBarry Smith builder.PETScMaker().run() 148105e34d4SBarry Smith import logger 149105e34d4SBarry Smith logger.Logger.defaultLog = None 150367c215cSLisandro Dalcin else: 151367c215cSLisandro Dalcin make = find_executable('make') 152*96fd8cd7SLisandro Dalcin command = [make, 'all'] 153*96fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 154367c215cSLisandro Dalcin if status != 0: raise RuntimeError(status) 155e68ebbecSBarry Smith 156*96fd8cd7SLisandro Dalcindef install(dest_dir, dry_run=False): 15765a891e7SLisandro Dalcin log.info('PETSc: install') 15865a891e7SLisandro Dalcin options = [ 15965a891e7SLisandro Dalcin '--destDir=' + dest_dir, 16065a891e7SLisandro Dalcin ] 161cb58ab5bSLisandro Dalcin log.info('install options:') 162cb58ab5bSLisandro Dalcin for opt in options: 163cb58ab5bSLisandro Dalcin log.info(' '*4 + opt) 16459e0f383SLisandro Dalcin # Run PETSc installer 165cb58ab5bSLisandro Dalcin if dry_run: return 166367c215cSLisandro Dalcin use_install_py = True 167367c215cSLisandro Dalcin if use_install_py: 168105e34d4SBarry Smith import install 16965a891e7SLisandro Dalcin install.Installer(options).run() 17065a891e7SLisandro Dalcin import logger 17165a891e7SLisandro Dalcin logger.Logger.defaultLog = None 172367c215cSLisandro Dalcin else: 173367c215cSLisandro Dalcin make = find_executable('make') 174*96fd8cd7SLisandro Dalcin command = [make, 'install', 'DESTDIR='+dest_dir] 175*96fd8cd7SLisandro Dalcin status = os.system(" ".join(command)) 176367c215cSLisandro Dalcin if status != 0: raise RuntimeError(status) 17799468c80SLisandro Dalcin 178*96fd8cd7SLisandro Dalcinclass context(object): 17999468c80SLisandro Dalcin def __init__(self): 18099468c80SLisandro Dalcin self.sys_argv = sys.argv[:] 18199468c80SLisandro Dalcin self.wdir = os.getcwd() 18299468c80SLisandro Dalcin def enter(self): 18399468c80SLisandro Dalcin del sys.argv[1:] 18499468c80SLisandro Dalcin pdir = os.environ['PETSC_DIR'] 18599468c80SLisandro Dalcin os.chdir(pdir) 18699468c80SLisandro Dalcin return self 18799468c80SLisandro Dalcin def exit(self): 18899468c80SLisandro Dalcin sys.argv[:] = self.sys_argv 18999468c80SLisandro Dalcin os.chdir(self.wdir) 190105e34d4SBarry Smith 19165a891e7SLisandro Dalcinclass cmd_install(_install): 19265a891e7SLisandro Dalcin 19341716173SLisandro Dalcin def initialize_options(self): 19441716173SLisandro Dalcin _install.initialize_options(self) 19541716173SLisandro Dalcin self.optimize = 1 19641716173SLisandro Dalcin 19765a891e7SLisandro Dalcin def run(self): 198*96fd8cd7SLisandro Dalcin root_dir = os.path.abspath(self.install_platlib) 199*96fd8cd7SLisandro Dalcin dest_dir = prefix = os.path.join(root_dir, 'petsc') 20099468c80SLisandro Dalcin # 20199468c80SLisandro Dalcin ctx = context().enter() 20265a891e7SLisandro Dalcin try: 203*96fd8cd7SLisandro Dalcin config(prefix, self.dry_run) 204*96fd8cd7SLisandro Dalcin build(self.dry_run) 205*96fd8cd7SLisandro Dalcin install(dest_dir, self.dry_run) 20665a891e7SLisandro Dalcin finally: 20799468c80SLisandro Dalcin ctx.exit() 208*96fd8cd7SLisandro Dalcin # 209*96fd8cd7SLisandro Dalcin self.outputs = [] 210*96fd8cd7SLisandro Dalcin for dirpath, _, filenames in os.walk(dest_dir): 211*96fd8cd7SLisandro Dalcin for fn in filenames: 212*96fd8cd7SLisandro Dalcin self.outputs.append(os.path.join(dirpath, fn)) 213*96fd8cd7SLisandro Dalcin # 214*96fd8cd7SLisandro Dalcin _install.run(self) 21565a891e7SLisandro Dalcin 216*96fd8cd7SLisandro Dalcin def get_outputs(self): 217*96fd8cd7SLisandro Dalcin outputs = getattr(self, 'outputs', []) 218*96fd8cd7SLisandro Dalcin outputs += _install.get_outputs(self) 219*96fd8cd7SLisandro Dalcin return outputs 220a32381aeSLisandro Dalcin 22165a891e7SLisandro Dalcindef version(): 2227d04d9c9SLisandro Dalcin import re 2237d04d9c9SLisandro Dalcin version_re = { 2247d04d9c9SLisandro Dalcin 'major' : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"), 2257d04d9c9SLisandro Dalcin 'minor' : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"), 2267d04d9c9SLisandro Dalcin 'micro' : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"), 2277d04d9c9SLisandro Dalcin 'patch' : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"), 2287d04d9c9SLisandro Dalcin 'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"), 2297d04d9c9SLisandro Dalcin } 2307d04d9c9SLisandro Dalcin petscversion_h = os.path.join('include','petscversion.h') 231*96fd8cd7SLisandro Dalcin data = open(petscversion_h, 'r').read() 2327d04d9c9SLisandro Dalcin major = int(version_re['major'].search(data).groups()[0]) 2337d04d9c9SLisandro Dalcin minor = int(version_re['minor'].search(data).groups()[0]) 2347d04d9c9SLisandro Dalcin micro = int(version_re['micro'].search(data).groups()[0]) 2357d04d9c9SLisandro Dalcin patch = int(version_re['patch'].search(data).groups()[0]) 2367d04d9c9SLisandro Dalcin release = int(version_re['release'].search(data).groups()[0]) 2377d04d9c9SLisandro Dalcin if release: 2387d04d9c9SLisandro Dalcin v = "%d.%d" % (major, minor) 2397d04d9c9SLisandro Dalcin if micro > 0: 2407d04d9c9SLisandro Dalcin v += ".%d" % micro 241247a1238SLisandro Dalcin #if patch > 0: 242247a1238SLisandro Dalcin # v += ".post%d" % patch 2437d04d9c9SLisandro Dalcin else: 24461a717f9SLisandro Dalcin v = "%d.%d.dev%d" % (major, minor+1, 0) 2457d04d9c9SLisandro Dalcin return v 24659e0f383SLisandro Dalcin 24765a891e7SLisandro Dalcindef tarball(): 24850f36069SLisandro Dalcin VERSION = version() 24950f36069SLisandro Dalcin if '.dev' in VERSION: 250a32381aeSLisandro Dalcin return None 2517d562c6eSLisandro Dalcin bits = VERSION.split('.') 2527d562c6eSLisandro Dalcin if len(bits) == 2: bits.append('0') 253247a1238SLisandro Dalcin PETSC_VERSION = '.'.join(bits[:3]) 25450f36069SLisandro Dalcin return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/' 255a9157d91SLisandro Dalcin 'petsc-lite-%s.tar.gz#egg=petsc-%s' % (PETSC_VERSION, VERSION)) 25665a891e7SLisandro Dalcin 25765a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3] 25865a891e7SLisandro Dalcinclassifiers = """ 259*96fd8cd7SLisandro DalcinDevelopment Status :: 5 - Production/Stable 26065a891e7SLisandro DalcinIntended Audience :: Developers 26165a891e7SLisandro DalcinIntended Audience :: Science/Research 262*96fd8cd7SLisandro DalcinLicense :: OSI Approved :: BSD License 263*96fd8cd7SLisandro DalcinOperating System :: POSIX 26465a891e7SLisandro DalcinProgramming Language :: C 26565a891e7SLisandro DalcinProgramming Language :: C++ 26665a891e7SLisandro DalcinProgramming Language :: Fortran 26765a891e7SLisandro DalcinProgramming Language :: Python 26865a891e7SLisandro DalcinTopic :: Scientific/Engineering 26965a891e7SLisandro DalcinTopic :: Software Development :: Libraries 27065a891e7SLisandro Dalcin""" 27165a891e7SLisandro Dalcin 27265a891e7SLisandro Dalcinbootstrap() 27365a891e7SLisandro Dalcinsetup(name='petsc', 27465a891e7SLisandro Dalcin version=version(), 27565a891e7SLisandro Dalcin description=description.pop(0), 27665a891e7SLisandro Dalcin long_description='\n'.join(description), 27765a891e7SLisandro Dalcin classifiers= classifiers.split('\n')[1:-1], 27865a891e7SLisandro Dalcin keywords = ['PETSc', 'MPI'], 27965a891e7SLisandro Dalcin platforms=['POSIX'], 28065a891e7SLisandro Dalcin license='PETSc', 28165a891e7SLisandro Dalcin 28265a891e7SLisandro Dalcin url='http://www.mcs.anl.gov/petsc/', 28365a891e7SLisandro Dalcin download_url=tarball(), 28465a891e7SLisandro Dalcin 28565a891e7SLisandro Dalcin author='PETSc Team', 28699468c80SLisandro Dalcin author_email='petsc-maint@mcs.anl.gov', 28765a891e7SLisandro Dalcin maintainer='Lisandro Dalcin', 28865a891e7SLisandro Dalcin maintainer_email='dalcinl@gmail.com', 28965a891e7SLisandro Dalcin 29065a891e7SLisandro Dalcin packages = ['petsc'], 2919fb7a39fSLisandro Dalcin package_dir = {'petsc': 'config/pypi'}, 292*96fd8cd7SLisandro Dalcin cmdclass={'install': cmd_install}, 29359e0f383SLisandro Dalcin **metadata) 294