Skip to content

Commit

Permalink
fortran compiler install help; clean and support install gfortran on …
Browse files Browse the repository at this point in the history
…Windows not in path
  • Loading branch information
cmbant committed Jan 28, 2019
1 parent 291d601 commit 4597087
Show file tree
Hide file tree
Showing 19 changed files with 332 additions and 197 deletions.
6 changes: 3 additions & 3 deletions README.rst
Expand Up @@ -5,7 +5,7 @@ CAMB
:Author: Antony Lewis and Anthony Challinor
:Homepage: https://camb.info/

.. image:: http://img.shields.io/pypi/v/camb.svg?style=flat
.. image:: https://img.shields.io/pypi/v/camb.svg?style=flat
:target: https://pypi.python.org/pypi/camb/
.. image:: https://readthedocs.org/projects/camb/badge/?version=latest
:target: https://camb.readthedocs.org/en/latest
Expand Down Expand Up @@ -62,12 +62,12 @@ The master branch contains latest changes to the main release version.
:target: https://mybinder.org/v2/gh/cmbant/camb/master?filepath=docs%2FCAMBdemo.ipynb

The devel branch contains latest less-stable things in development.
The master and devel branches have an integrated test suite, which runs automatically on `Travis <http://travis-ci.org>`_ for new commits and pull requests.
The master and devel branches have an integrated test suite, which runs automatically on `Travis <https://travis-ci.org>`_ for new commits and pull requests.
Reference results and test outputs are stored in the `test outputs repository <https://github.com/cmbant/CAMB_test_outputs/>`_. Tests can also be run locally.

To reproduce legacy results, see these branches:

- *CAMB_sources* is the old public `CAMB Sources <http://camb.info/sources/>`_ code.
- *CAMB_sources* is the old public `CAMB Sources <https://camb.info/sources/>`_ code.
- *CAMB_v0* is the old Fortran-oriented (gfortran 4.8-compatible) version as used by the Planck 2018 analysis.
- *rayleigh* includes frequency-dependent Rayleigh scattering

Expand Down
116 changes: 116 additions & 0 deletions camb/_compilers.py
@@ -0,0 +1,116 @@
import subprocess
import os
import struct
import platform
import re
import io
from pkg_resources import parse_version

is_windows = platform.system() == "Windows"

is_32_bit = struct.calcsize("P") == 4

compiler_environ = os.environ.copy()

gfortran_min = '6'
gfortran_bits = ('x86_64', 'i686')[is_32_bit]


def call_command(cmd):
try:
return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, env=compiler_environ).decode().strip()
except:
return None


def get_ifort_version():
return call_command("ifort -v")


def get_gfortran_version():
return call_command("gfortran -dumpversion")


def check_ifort():
return get_ifort_version() or False


def check_gfortran(version=gfortran_min, msg=False, retry=False):
global compiler_environ
gfortran_version = get_gfortran_version()
version = str(version)
if gfortran_version:
ok = parse_version(version) <= parse_version(gfortran_version)
else:
ok = False
if not ok and is_windows and not retry:
mingw = os.path.join(os.environ["ProgramFiles"], 'mingw-w64')
best_version = gfortran_min
if os.path.isdir(mingw):
# look for mingw installation
dirs = [name for name in os.listdir(mingw) if
gfortran_bits in name and os.path.isdir(os.path.join(mingw, name))]
path = None
for i, x in enumerate(dirs):
ver = x.split('-')[1]
if parse_version(best_version) <= parse_version(ver):
best_version = ver
path = x
if path:
newpath = os.path.join(mingw, path, 'mingw64', 'bin')
if os.path.exists(os.path.join(newpath, 'gfortran.exe')):
if not compiler_environ["PATH"].startswith(newpath):
compiler_environ["PATH"] = newpath + ';' + compiler_environ["PATH"]
return check_gfortran(version, msg, retry=True)
if ok and is_windows:
version_str = str(subprocess.check_output("gfortran -dumpmachine", shell=True, env=compiler_environ))
ok = gfortran_bits in version_str
if not ok and msg:
raise Exception(
'You need ifort or gfortran %s or higher to compile (found: %s).\nSee %s' % (
version, gfortran_version, 'https://camb.readthedocs.io/en/latest/fortran_compilers.html'))

return ok, gfortran_version


def makefile_dict(filename):
# this is very non-general, just enough for pulling source file names from Makefile
with io.open(filename, 'r') as f:
lines = f.readlines()
vals = {}
lastval = None
append = False
for line in lines:
parts = line.split('\\')
line = parts[0].strip()
if '?=' in line:
key, val = line.split('?=')
env = os.environ.get(key.strip(), None)
if env:
vals[key] = env
lastval = None
append = False
continue
else:
line = line.replace('?=', '=')
if append and lastval:
vals[lastval] += ' ' + line
elif '=' in line:
if len(line.split('=')) == 2 and ':' not in line:
lastval, value = line.split('=')
lastval = lastval.strip()
vals[lastval] = value.strip()
else:
lastval = None
append = len(parts) > 1

def repl(groups):
if groups.group(1) in vals:
return vals[groups.group(1)]
else:
return groups.group(0)

for key, value in vals.items():
if '$' in value:
vals[key] = re.sub(r'\$\((\w+)\)', repl, value)
return vals
Binary file modified camb/cambdll.dll
Binary file not shown.
8 changes: 4 additions & 4 deletions camb/correlations.py
Expand Up @@ -249,7 +249,7 @@ def lensed_correlations(cls, clpp, xvals, weights=None, lmax=None, delta=False,
lensed correlations and lensed cls.
Uses the non-perturbative curved-sky results from Eqs 9.12 and 9.16-9.18 of
`astro-ph/0601594 <http://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
`astro-ph/0601594 <https://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
:param cls: 2D array of unlensed cls(L,ix), with L (:math:`\equiv\ell`) starting at zero and ix=0,1,2,3 in order TT, EE, BB, TE.
cls should include :math:`\ell(\ell+1)/2\pi` factors.
Expand Down Expand Up @@ -371,7 +371,7 @@ def lensed_cls(cls, clpp, lmax=None, lmax_lensed=None, sampling_factor=1.4, delt
r"""
Get the lensed power spectra from the unlensed power spectra and the lensing potential power.
Uses the non-perturbative curved-sky results from Eqs 9.12 and 9.16-9.18 of
`astro-ph/0601594 <http://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`.
`astro-ph/0601594 <https://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`.
Correlations are calculated for Gauss-Legendre integration if leggaus=True; this slows it by several seconds,
but will be must faster on subsequent calls with the same lmax*sampling_factor.
Expand Down Expand Up @@ -426,7 +426,7 @@ def lensed_cl_derivatives(cls, clpp, lmax=None, theta_max=np.pi / 32,
is given by dcl[ix,:,:].dot(np.ones(clpp.shape)).
Uses the non-perturbative curved-sky results from Eqs 9.12 and 9.16-9.18 of
`astro-ph/0601594 <http://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
`astro-ph/0601594 <https://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
:param cls: 2D array of unlensed cls(L,ix), with L starting at zero and ix=0,1,2,3 in order TT, EE, BB, TE.
cls should include :math:`\ell(\ell+1)/2\pi` factors.
Expand Down Expand Up @@ -567,7 +567,7 @@ def lensed_cl_derivative_unlensed(clpp, lmax=None, theta_max=np.pi / 32,
where cl is the appropriate :math:`\ell(\ell+1)C^{\rm unlens}_\ell/2\pi`.
Uses the non-perturbative curved-sky results from Eqs 9.12 and 9.16-9.18 of
`astro-ph/0601594 <http://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
`astro-ph/0601594 <https://arxiv.org/abs/astro-ph/0601594>`_, to second order in :math:`C_{{\rm gl},2}`
:param clpp: array of :math:`[L(L+1)]^2 C_L^{\phi\phi}/2\pi` lensing potential power spectrum (zero based)
:param lmax: optional maximum L to use from the clpp array
Expand Down
4 changes: 2 additions & 2 deletions camb/dark_energy.py
Expand Up @@ -83,7 +83,7 @@ def validate_params(self):
@fortran_class
class DarkEnergyPPF(DarkEnergyEqnOfState):
"""
Class implementating the w, wa or splined w(a) parameterization in the PPF perturbation approximation (`arXiv:0808.3125 <http://arxiv.org/abs/0808.3125>`_)
Class implementating the w, wa or splined w(a) parameterization in the PPF perturbation approximation (`arXiv:0808.3125 <https://arxiv.org/abs/0808.3125>`_)
Use inherited methods to set parameters or interpolation table.
"""
Expand All @@ -95,7 +95,7 @@ class DarkEnergyPPF(DarkEnergyEqnOfState):
@fortran_class
class AxionEffectiveFluid(DarkEnergyModel):
"""
Example implementation of a specifc (early) dark energy fluid model (`arXiv:1806.10608 <http://arxiv.org/abs/1806.10608>`_).
Example implementation of a specifc (early) dark energy fluid model (`arXiv:1806.10608 <https://arxiv.org/abs/1806.10608>`_).
Not well tested, but should serve to demonstrate how to make your own custom classes.
"""
_fields_ = [
Expand Down
4 changes: 2 additions & 2 deletions camb/emission_angle.py
@@ -1,6 +1,6 @@
"""
This module calculates the corrections to the standard lensed CMB power spectra results due to time delay and
emission angle, following `arXiv:1706.02673 <http://arxiv.org/abs/1706.02673>`_. This can be combined with the result
emission angle, following `arXiv:1706.02673 <https://arxiv.org/abs/1706.02673>`_. This can be combined with the result
from the postborn module to estimate the leading corrections to the standard lensing B modes.
Corrections to T and E are negligible, and not calculated. The result for BB includes approximately contributions
Expand Down Expand Up @@ -64,7 +64,7 @@ def get_emission_delay_BB(params, kmax=100, lmax=3000, non_linear=True, CMB_unit
acc=1, lsamp=None, return_terms=False, include_reionization=True):
r"""
Get B modes from emission angle and time delay effects.
Uses full-sky result from appendix of `arXiv:1706.02673 <http://arxiv.org/abs/1706.02673>`_
Uses full-sky result from appendix of `arXiv:1706.02673 <https://arxiv.org/abs/1706.02673>`_
:param params: :class:`.model.CAMBparams` instance with cosmological parameters etc.
:param kmax: maximum k (in :math:`{\rm Mpc}^{-1}` units)
Expand Down
14 changes: 7 additions & 7 deletions camb/nonlinear.py
Expand Up @@ -47,14 +47,14 @@ def set_params(self, halofit_version=halofit_default):
:param version: One of
- original: `astro-ph/0207664 <http://arxiv.org/abs/astro-ph/0207664>`_
- bird: `arXiv:1109.4416 <http://arxiv.org/abs/1109.4416>`_
- original: `astro-ph/0207664 <https://arxiv.org/abs/astro-ph/0207664>`_
- bird: `arXiv:1109.4416 <https://arxiv.org/abs/1109.4416>`_
- peacock: `Peacock fit <http://www.roe.ac.uk/~jap/haloes/>`_
- takahashi: `arXiv:1208.2701 <http://arxiv.org/abs/1208.2701>`_
- mead: HMCode `arXiv:1602.02154 <http://arxiv.org/abs/1602.02154>`_
- takahashi: `arXiv:1208.2701 <https://arxiv.org/abs/1208.2701>`_
- mead: HMCode `arXiv:1602.02154 <https://arxiv.org/abs/1602.02154>`_
- halomodel: basic halomodel
- casarini: PKequal `arXiv:0810.0190 <http://arxiv.org/abs/0810.0190>`_, `arXiv:1601.07230 <http://arxiv.org/abs/1601.07230>`_
- mead2015: original 2015 version of HMCode `arXiv:1505.07833 <http://arxiv.org/abs/1505.07833>`_
- casarini: PKequal `arXiv:0810.0190 <https://arxiv.org/abs/0810.0190>`_, `arXiv:1601.07230 <https://arxiv.org/abs/1601.07230>`_
- mead2015: original 2015 version of HMCode `arXiv:1505.07833 <https://arxiv.org/abs/1505.07833>`_
"""
self.halofit_version = halofit_version
Expand All @@ -67,7 +67,7 @@ class SecondOrderPK(NonLinearModel):
Only intended for use at very high redshift (z>10) where corrections are perturbative, it will not give
sensible results at low redshift.
See Appendix F of `astro-ph/0702600 <http://arxiv.org/abs/astro-ph/0702600>`_ for equations and references.
See Appendix F of `astro-ph/0702600 <https://arxiv.org/abs/astro-ph/0702600>`_ for equations and references.
Not intended for production use, it's mainly to serve as an example alternative non-linear model implementation.
"""
Expand Down
4 changes: 2 additions & 2 deletions camb/postborn.py
Expand Up @@ -31,7 +31,7 @@ def cl_kappa_limber(results, PK, ls, nz, chi_source, chi_source2=None):
def get_field_rotation_power(params, kmax=100, lmax=20000, non_linear=True, z_source=None,
k_per_logint=None, acc=1, lsamp=None):
r"""
Get field rotation power spectrum, :math:`C_L^{\omega\omega}`, following `arXiv:1605.05662 <http://arxiv.org/abs/1605.05662>`_
Get field rotation power spectrum, :math:`C_L^{\omega\omega}`, following `arXiv:1605.05662 <https://arxiv.org/abs/1605.05662>`_
Uses lowest Limber approximation.
:param params: :class:`.model.CAMBparams` instance with cosmological parameters etc.
Expand Down Expand Up @@ -164,7 +164,7 @@ def high_curl_integrand(ll, lp):
def get_field_rotation_BB(params, lmax=None, acc=1, CMB_unit='muK', raw_cl=False, spline=True):
r"""
Get the B-mode power spectrum from field post-born field rotation, based on perturbative and Limber approximations.
See `arXiv:1605.05662 <http://arxiv.org/abs/1605.05662>`_.
See `arXiv:1605.05662 <https://arxiv.org/abs/1605.05662>`_.
:param params: :class:`.model.CAMBparams` instance with cosmological parameters etc.
:param lmax: maximum :math:`\ell`
Expand Down
2 changes: 1 addition & 1 deletion camb/reionization.py
Expand Up @@ -14,7 +14,7 @@ class ReionizationModel(F2003Class):
class TanhReionization(ReionizationModel):
"""
This default (unphysical) tanh x_e parameterization is described in
Appendix B of `arXiv:0804.3865 <http://arxiv.org/abs/0804.3865>`_
Appendix B of `arXiv:0804.3865 <https://arxiv.org/abs/0804.3865>`_
"""
_fields_ = [
("use_optical_depth", c_bool, "Whether to use the optical depth or redshift paramters"),
Expand Down
17 changes: 12 additions & 5 deletions camb/symbolic.py
Expand Up @@ -713,6 +713,9 @@ def get_default_compiler():
return _default_compiler


_first_compile = True


def compile_source_function_code(code_body, file_path='', compiler=None, fflags=None, cache=True):
"""
Compile fortran code into function pointer in compiled shared library.
Expand Down Expand Up @@ -758,14 +761,18 @@ def compile_source_function_code(code_body, file_path='', compiler=None, fflags=
end function
"""

import subprocess, tempfile, struct, platform
import subprocess, tempfile
from ._compilers import is_32_bit, is_windows, compiler_environ, check_gfortran

compiler = compiler or get_default_compiler()
fflags = fflags or _default_flags

if struct.calcsize("P") == 4: fflags = "-m32 " + fflags
if platform.system() == "Windows": fflags += ' -static'

if is_32_bit: fflags = "-m32 " + fflags
if is_windows:
global _first_compile
fflags += ' -static'
if _first_compile:
check_gfortran(msg=True)
workdir = file_path or tempfile.gettempdir()
if not os.access(workdir, os.F_OK):
os.mkdir(workdir)
Expand All @@ -791,7 +798,7 @@ def compile_source_function_code(code_body, file_path='', compiler=None, fflags=

command = " ".join([compiler, fflags, source_file, "-o", dll_name])
try:
subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True, cwd=workdir)
subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True, cwd=workdir, env=compiler_environ)
except subprocess.CalledProcessError as E:
print(command)
print('Error compiling generated code:')
Expand Down
2 changes: 1 addition & 1 deletion docs/README_pypi.rst
Expand Up @@ -5,7 +5,7 @@ CAMB
:Author: Antony Lewis and Anthony Challinor
:Homepage: https://camb.info/

.. image:: http://img.shields.io/pypi/v/camb.svg?style=flat
.. image:: https://img.shields.io/pypi/v/camb.svg?style=flat
:target: https://pypi.python.org/pypi/camb/
.. image:: https://readthedocs.org/projects/camb/badge/?version=latest
:target: https://camb.readthedocs.org/en/latest
Expand Down

0 comments on commit 4597087

Please sign in to comment.