xref: /petsc/setup.py (revision 93b33a5a06547f1b4f1b814df460a36e585df5ed)
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
13*93b33a5aSLisandro Dalcin.. note::
14*93b33a5aSLisandro Dalcin
15*93b33a5aSLisandro Dalcin   To install ``PETSc`` and ``petsc4py`` (``mpi4py`` is optional
16*93b33a5aSLisandro Dalcin   but highly recommended) use::
17*93b33a5aSLisandro Dalcin
18*93b33a5aSLisandro Dalcin     $ pip install numpy mpi4py
19*93b33a5aSLisandro Dalcin     $ pip install petsc petsc4py
20*93b33a5aSLisandro Dalcin
21922ada92SLisandro Dalcin.. tip::
22922ada92SLisandro Dalcin
23*93b33a5aSLisandro Dalcin  You can also install the in-development versions with::
24922ada92SLisandro Dalcin
25*93b33a5aSLisandro Dalcin    $ pip install Cython numpy mpi4py
26*93b33a5aSLisandro Dalcin    $ pip install --no-deps https://bitbucket.org/petsc/petsc/get/master.tar.gz
27*93b33a5aSLisandro Dalcin    $ pip install --no-deps https://bitbucket.org/petsc/petsc4py/get/master.tar.gz
28922ada92SLisandro Dalcin
29e68ebbecSBarry Smith"""
30e68ebbecSBarry Smith
3165a891e7SLisandro Dalcinimport sys, os
3265a891e7SLisandro Dalcinfrom distutils.core import setup
33cb58ab5bSLisandro Dalcinfrom distutils.util import get_platform, split_quoted
34b88f8b63SLisandro Dalcinfrom distutils.spawn import find_executable
3565a891e7SLisandro Dalcinfrom distutils.command.build import build as _build
3665a891e7SLisandro Dalcinif 'setuptools' in sys.modules:
3765a891e7SLisandro Dalcin    from setuptools.command.install import install as _install
3865a891e7SLisandro Dalcinelse:
3965a891e7SLisandro Dalcin    from distutils.command.install import install as _install
40a32381aeSLisandro Dalcinfrom distutils.command.sdist import sdist as _sdist
4165a891e7SLisandro Dalcinfrom distutils import log
4212c1d45bSMatthew G Knepley
4365a891e7SLisandro Dalcininit_py = """\
44a32381aeSLisandro Dalcin# Author:  PETSc Team
45a597b971SLisandro Dalcin# Contact: petsc-maint@mcs.anl.gov
4665a891e7SLisandro Dalcin
4765a891e7SLisandro Dalcindef get_petsc_dir():
4865a891e7SLisandro Dalcin    import os
4965a891e7SLisandro Dalcin    return os.path.dirname(__file__)
5065a891e7SLisandro Dalcin
51a32381aeSLisandro Dalcindef get_config():
52a32381aeSLisandro Dalcin    conf = {}
539fb7a39fSLisandro Dalcin    conf['PETSC_DIR'] = get_petsc_dir()
54a32381aeSLisandro Dalcin    return conf
5565a891e7SLisandro Dalcin"""
5665a891e7SLisandro Dalcin
5759e0f383SLisandro Dalcinmetadata = {
5859e0f383SLisandro Dalcin    'provides' : ['petsc'],
5959e0f383SLisandro Dalcin    'requires' : [],
6059e0f383SLisandro Dalcin}
6159e0f383SLisandro Dalcin
6265a891e7SLisandro Dalcindef bootstrap():
63cb58ab5bSLisandro Dalcin    # Set PETSC_DIR and PETSC_ARCH
6465a891e7SLisandro Dalcin    PETSC_DIR  = os.path.abspath(os.getcwd())
6565a891e7SLisandro Dalcin    PETSC_ARCH = get_platform() + '-python'
6665a891e7SLisandro Dalcin    os.environ['PETSC_DIR']  = PETSC_DIR
6765a891e7SLisandro Dalcin    os.environ['PETSC_ARCH'] = PETSC_ARCH
6865a891e7SLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
69*93b33a5aSLisandro Dalcin    sys.path.insert(0, os.path.join(PETSC_DIR, 'conf'))
7059e0f383SLisandro Dalcin    # Generate package __init__.py file
719fb7a39fSLisandro Dalcin    from distutils.dir_util import mkpath
729fb7a39fSLisandro Dalcin    pkgdir = os.path.join('config', 'pypi')
730ddf2052SLisandro Dalcin    if not os.path.exists(pkgdir): mkpath(pkgdir)
749fb7a39fSLisandro Dalcin    pkgfile = os.path.join(pkgdir, '__init__.py')
75922ada92SLisandro Dalcin    fh = open(pkgfile, 'wt')
76922ada92SLisandro Dalcin    fh.write(init_py)
77922ada92SLisandro Dalcin    fh.close()
7859e0f383SLisandro Dalcin    # Simple-minded lookup for MPI and mpi4py
7959e0f383SLisandro Dalcin    mpi4py = mpicc = None
8059e0f383SLisandro Dalcin    try:
8159e0f383SLisandro Dalcin        import mpi4py
8259e0f383SLisandro Dalcin        conf = mpi4py.get_config()
8359e0f383SLisandro Dalcin        mpicc = conf.get('mpicc')
8459e0f383SLisandro Dalcin    except ImportError: # mpi4py is not installed
85922ada92SLisandro Dalcin        mpi4py = None
8659e0f383SLisandro Dalcin        mpicc = os.environ.get('MPICC') or find_executable('mpicc')
871b095333SLisandro Dalcin    except AttributeError: # mpi4py is too old
8859e0f383SLisandro Dalcin        pass
89922ada92SLisandro Dalcin    if ('setuptools' in sys.modules):
90be96eb59SLisandro Dalcin        metadata['zip_safe'] = False
91922ada92SLisandro Dalcin        if not mpi4py and mpicc:
92922ada92SLisandro Dalcin            metadata['install_requires']= ['mpi4py>=1.2.2']
9365a891e7SLisandro Dalcin
9465a891e7SLisandro Dalcindef config(dry_run=False):
9565a891e7SLisandro Dalcin    log.info('PETSc: configure')
9665a891e7SLisandro Dalcin    options = [
9765a891e7SLisandro Dalcin        'PETSC_ARCH='+os.environ['PETSC_ARCH'],
98cb58ab5bSLisandro Dalcin        '--with-shared-libraries=1',
9911035aebSLisandro Dalcin        '--with-debugging=0',
100922ada92SLisandro Dalcin        '--with-c2html=0', # not needed
10165a891e7SLisandro Dalcin        ]
10259e0f383SLisandro Dalcin    # MPI
10359e0f383SLisandro Dalcin    try:
10459e0f383SLisandro Dalcin        import mpi4py
10559e0f383SLisandro Dalcin        conf = mpi4py.get_config()
10659e0f383SLisandro Dalcin        mpicc  = conf.get('mpicc')
107cb58ab5bSLisandro Dalcin        mpicxx = conf.get('mpicxx')
108cb58ab5bSLisandro Dalcin        mpif90 = conf.get('mpif90')
10959e0f383SLisandro Dalcin    except (ImportError, AttributeError):
11059e0f383SLisandro Dalcin        mpicc  = os.environ.get('MPICC')  or find_executable('mpicc')
111cb58ab5bSLisandro Dalcin        mpicxx = os.environ.get('MPICXX') or find_executable('mpicxx')
112cb58ab5bSLisandro Dalcin        mpif90 = os.environ.get('MPIF90') or find_executable('mpif90')
11359e0f383SLisandro Dalcin    if mpicc:
11459e0f383SLisandro Dalcin        options.append('--with-cc='+mpicc)
115cb58ab5bSLisandro Dalcin        if mpicxx:
116cb58ab5bSLisandro Dalcin            options.append('--with-cxx='+mpicxx)
117*93b33a5aSLisandro Dalcin        else:
118*93b33a5aSLisandro Dalcin            options.append('--with-cxx=0')
119cb58ab5bSLisandro Dalcin        if mpif90:
120cb58ab5bSLisandro Dalcin            options.append('--with-fc='+mpif90)
12159e0f383SLisandro Dalcin        else:
122*93b33a5aSLisandro Dalcin            options.append('--with-fc=0')
123*93b33a5aSLisandro Dalcin            options.append('--with-sowing=0')
124*93b33a5aSLisandro Dalcin    else:
12559e0f383SLisandro Dalcin        options.append('--with-mpi=0')
126cb58ab5bSLisandro Dalcin    # Extra configure options
127cb58ab5bSLisandro Dalcin    config_opts = os.environ.get('PETSC_CONFIGURE_OPTIONS', '')
128cb58ab5bSLisandro Dalcin    config_opts = split_quoted(config_opts)
129cb58ab5bSLisandro Dalcin    options.extend(config_opts)
130cb58ab5bSLisandro Dalcin    log.info('configure options:')
131cb58ab5bSLisandro Dalcin    for opt in options:
132cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
13359e0f383SLisandro Dalcin    # Run PETSc configure
134cb58ab5bSLisandro Dalcin    if dry_run: return
135e68ebbecSBarry Smith    import configure
13665a891e7SLisandro Dalcin    configure.petsc_configure(options)
137e68ebbecSBarry Smith    import logger
138e68ebbecSBarry Smith    logger.Logger.defaultLog = None
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')
152367c215cSLisandro Dalcin        status = os.system(" ".join(
153367c215cSLisandro Dalcin                [make, 'all']
154367c215cSLisandro Dalcin                ))
155367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
156e68ebbecSBarry Smith
15765a891e7SLisandro Dalcindef install(dest_dir, prefix=None, dry_run=False):
15865a891e7SLisandro Dalcin    log.info('PETSc: install')
15965a891e7SLisandro Dalcin    if prefix is None:
16065a891e7SLisandro Dalcin        prefix = dest_dir
16165a891e7SLisandro Dalcin    options = [
16265a891e7SLisandro Dalcin        '--destDir=' + dest_dir,
1634dee622bSLisandro Dalcin        '--prefix='  + prefix,
16465a891e7SLisandro Dalcin        ]
165cb58ab5bSLisandro Dalcin    log.info('install options:')
166cb58ab5bSLisandro Dalcin    for opt in options:
167cb58ab5bSLisandro Dalcin        log.info(' '*4 + opt)
16859e0f383SLisandro Dalcin    # Run PETSc installer
169cb58ab5bSLisandro Dalcin    if dry_run: return
170367c215cSLisandro Dalcin    use_install_py = True
171367c215cSLisandro Dalcin    if use_install_py:
172105e34d4SBarry Smith        import install
17365a891e7SLisandro Dalcin        install.Installer(options).run()
17465a891e7SLisandro Dalcin        import logger
17565a891e7SLisandro Dalcin        logger.Logger.defaultLog = None
176367c215cSLisandro Dalcin    else:
177367c215cSLisandro Dalcin        make = find_executable('make')
178367c215cSLisandro Dalcin        status = os.system(" ".join(
179367c215cSLisandro Dalcin                [make, 'install', 'DESTDIR='+dest_dir]
180367c215cSLisandro Dalcin                ))
181367c215cSLisandro Dalcin        if status != 0: raise RuntimeError(status)
18299468c80SLisandro Dalcin
18399468c80SLisandro Dalcinclass context:
18499468c80SLisandro Dalcin    def __init__(self):
18599468c80SLisandro Dalcin        self.sys_argv = sys.argv[:]
18699468c80SLisandro Dalcin        self.wdir = os.getcwd()
18799468c80SLisandro Dalcin    def enter(self):
18899468c80SLisandro Dalcin        del sys.argv[1:]
18999468c80SLisandro Dalcin        pdir = os.environ['PETSC_DIR']
19099468c80SLisandro Dalcin        os.chdir(pdir)
19199468c80SLisandro Dalcin        return self
19299468c80SLisandro Dalcin    def exit(self):
19399468c80SLisandro Dalcin        sys.argv[:] = self.sys_argv
19499468c80SLisandro Dalcin        os.chdir(self.wdir)
195105e34d4SBarry Smith
19665a891e7SLisandro Dalcinclass cmd_build(_build):
19765a891e7SLisandro Dalcin
198a597b971SLisandro Dalcin    def initialize_options(self):
199a597b971SLisandro Dalcin        _build.initialize_options(self)
200a597b971SLisandro Dalcin        PETSC_ARCH = os.environ.get('PETSC_ARCH', '')
201a597b971SLisandro Dalcin        self.build_base = os.path.join(PETSC_ARCH, 'build-python')
202a597b971SLisandro Dalcin
20365a891e7SLisandro Dalcin    def run(self):
20465a891e7SLisandro Dalcin        _build.run(self)
20599468c80SLisandro Dalcin        ctx = context().enter()
20665a891e7SLisandro Dalcin        try:
20765a891e7SLisandro Dalcin            config(self.dry_run)
20865a891e7SLisandro Dalcin            build(self.dry_run)
20965a891e7SLisandro Dalcin        finally:
21099468c80SLisandro Dalcin            ctx.exit()
21165a891e7SLisandro Dalcin
21265a891e7SLisandro Dalcinclass cmd_install(_install):
21365a891e7SLisandro Dalcin
21441716173SLisandro Dalcin    def initialize_options(self):
21541716173SLisandro Dalcin        _install.initialize_options(self)
21641716173SLisandro Dalcin        self.optimize = 1
21741716173SLisandro Dalcin
21865a891e7SLisandro Dalcin    def run(self):
21965a891e7SLisandro Dalcin        root_dir = self.install_platlib
22065a891e7SLisandro Dalcin        dest_dir = os.path.join(root_dir, 'petsc')
22165a891e7SLisandro Dalcin        bdist_base = self.get_finalized_command('bdist').bdist_base
22265a891e7SLisandro Dalcin        if dest_dir.startswith(bdist_base):
22365a891e7SLisandro Dalcin            prefix = dest_dir[len(bdist_base)+1:]
22465a891e7SLisandro Dalcin            prefix = prefix[prefix.index(os.path.sep):]
22565a891e7SLisandro Dalcin        else:
22665a891e7SLisandro Dalcin            prefix = dest_dir
22765a891e7SLisandro Dalcin        dest_dir = os.path.abspath(dest_dir)
22865a891e7SLisandro Dalcin        prefix   = os.path.abspath(prefix)
22999468c80SLisandro Dalcin        #
23099468c80SLisandro Dalcin        _install.run(self)
23199468c80SLisandro Dalcin        ctx = context().enter()
23265a891e7SLisandro Dalcin        try:
23365a891e7SLisandro Dalcin            install(dest_dir, prefix, self.dry_run)
23465a891e7SLisandro Dalcin        finally:
23599468c80SLisandro Dalcin            ctx.exit()
23665a891e7SLisandro Dalcin
237a32381aeSLisandro Dalcinclass cmd_sdist(_sdist):
238a32381aeSLisandro Dalcin
239a32381aeSLisandro Dalcin    def initialize_options(self):
240a32381aeSLisandro Dalcin        _sdist.initialize_options(self)
241a32381aeSLisandro Dalcin        self.force_manifest = 1
24299468c80SLisandro Dalcin        self.template = os.path.join('config', 'manifest.in')
243a32381aeSLisandro Dalcin
24465a891e7SLisandro Dalcindef version():
2457d04d9c9SLisandro Dalcin    import re
2467d04d9c9SLisandro Dalcin    version_re = {
2477d04d9c9SLisandro Dalcin        'major'  : re.compile(r"#define\s+PETSC_VERSION_MAJOR\s+(\d+)"),
2487d04d9c9SLisandro Dalcin        'minor'  : re.compile(r"#define\s+PETSC_VERSION_MINOR\s+(\d+)"),
2497d04d9c9SLisandro Dalcin        'micro'  : re.compile(r"#define\s+PETSC_VERSION_SUBMINOR\s+(\d+)"),
2507d04d9c9SLisandro Dalcin        'patch'  : re.compile(r"#define\s+PETSC_VERSION_PATCH\s+(\d+)"),
2517d04d9c9SLisandro Dalcin        'release': re.compile(r"#define\s+PETSC_VERSION_RELEASE\s+(\d+)"),
2527d04d9c9SLisandro Dalcin        }
2537d04d9c9SLisandro Dalcin    petscversion_h = os.path.join('include','petscversion.h')
2547d04d9c9SLisandro Dalcin    data = open(petscversion_h, 'rt').read()
2557d04d9c9SLisandro Dalcin    major = int(version_re['major'].search(data).groups()[0])
2567d04d9c9SLisandro Dalcin    minor = int(version_re['minor'].search(data).groups()[0])
2577d04d9c9SLisandro Dalcin    micro = int(version_re['micro'].search(data).groups()[0])
2587d04d9c9SLisandro Dalcin    patch = int(version_re['patch'].search(data).groups()[0])
2597d04d9c9SLisandro Dalcin    release = int(version_re['release'].search(data).groups()[0])
2607d04d9c9SLisandro Dalcin    if release:
2617d04d9c9SLisandro Dalcin        v = "%d.%d" % (major, minor)
2627d04d9c9SLisandro Dalcin        if micro > 0:
2637d04d9c9SLisandro Dalcin            v += ".%d" % micro
264247a1238SLisandro Dalcin        #if patch > 0:
265247a1238SLisandro Dalcin        #    v += ".post%d" % patch
2667d04d9c9SLisandro Dalcin    else:
26761a717f9SLisandro Dalcin        v = "%d.%d.dev%d" % (major, minor+1, 0)
2687d04d9c9SLisandro Dalcin    return v
26959e0f383SLisandro Dalcin
27065a891e7SLisandro Dalcindef tarball():
27150f36069SLisandro Dalcin    VERSION = version()
27250f36069SLisandro Dalcin    if '.dev' in VERSION:
273a32381aeSLisandro Dalcin        return None
2747d562c6eSLisandro Dalcin    bits = VERSION.split('.')
2757d562c6eSLisandro Dalcin    if len(bits) == 2: bits.append('0')
276247a1238SLisandro Dalcin    PETSC_VERSION = '.'.join(bits[:3])
27750f36069SLisandro Dalcin    return ('http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/'
278a9157d91SLisandro Dalcin            'petsc-lite-%s.tar.gz#egg=petsc-%s' % (PETSC_VERSION, VERSION))
27965a891e7SLisandro Dalcin
28065a891e7SLisandro Dalcindescription = __doc__.split('\n')[1:-1]; del description[1:3]
28165a891e7SLisandro Dalcinclassifiers = """
28265a891e7SLisandro DalcinLicense :: Public Domain
28365a891e7SLisandro DalcinOperating System :: POSIX
28465a891e7SLisandro DalcinIntended Audience :: Developers
28565a891e7SLisandro DalcinIntended Audience :: Science/Research
28665a891e7SLisandro DalcinProgramming Language :: C
28765a891e7SLisandro DalcinProgramming Language :: C++
28865a891e7SLisandro DalcinProgramming Language :: Fortran
28965a891e7SLisandro DalcinProgramming Language :: Python
29065a891e7SLisandro DalcinTopic :: Scientific/Engineering
29165a891e7SLisandro DalcinTopic :: Software Development :: Libraries
29265a891e7SLisandro Dalcin"""
29365a891e7SLisandro Dalcin
29465a891e7SLisandro Dalcinbootstrap()
29565a891e7SLisandro Dalcinsetup(name='petsc',
29665a891e7SLisandro Dalcin      version=version(),
29765a891e7SLisandro Dalcin      description=description.pop(0),
29865a891e7SLisandro Dalcin      long_description='\n'.join(description),
29965a891e7SLisandro Dalcin      classifiers= classifiers.split('\n')[1:-1],
30065a891e7SLisandro Dalcin      keywords = ['PETSc', 'MPI'],
30165a891e7SLisandro Dalcin      platforms=['POSIX'],
30265a891e7SLisandro Dalcin      license='PETSc',
30365a891e7SLisandro Dalcin
30465a891e7SLisandro Dalcin      url='http://www.mcs.anl.gov/petsc/',
30565a891e7SLisandro Dalcin      download_url=tarball(),
30665a891e7SLisandro Dalcin
30765a891e7SLisandro Dalcin      author='PETSc Team',
30899468c80SLisandro Dalcin      author_email='petsc-maint@mcs.anl.gov',
30965a891e7SLisandro Dalcin      maintainer='Lisandro Dalcin',
31065a891e7SLisandro Dalcin      maintainer_email='dalcinl@gmail.com',
31165a891e7SLisandro Dalcin
31265a891e7SLisandro Dalcin      packages = ['petsc'],
3139fb7a39fSLisandro Dalcin      package_dir = {'petsc': 'config/pypi'},
31465a891e7SLisandro Dalcin      cmdclass={
31565a891e7SLisandro Dalcin        'build': cmd_build,
31665a891e7SLisandro Dalcin        'install': cmd_install,
317a32381aeSLisandro Dalcin        'sdist': cmd_sdist,
31865a891e7SLisandro Dalcin        },
31959e0f383SLisandro Dalcin      **metadata)
320