xref: /petsc/setup.py (revision 96fd8cd7e1ba288d4699722afd617a43bdf631a7)
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