diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 564fe979..d94bc7de 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -4,7 +4,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + branches: [ master, cmake-dev ] # don't run the CRON part in my fork # schedule: # - cron: "0 0 * * *" @@ -42,3 +42,44 @@ jobs: - name: Test pypolychord (MPI) run: mpirun -np 2 python run_pypolychord.py + + pip_macos: + runs-on: macos-12 + # env: + # FC: gfortran-11 + # # CXX: gcc-11 + # CXX: gfortran-11 + strategy: + matrix: + # cc: [gcc] + cc: [clang] + python-version: [3.9.13] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + brew install cmake openmpi gcc gfortran + python -m pip install --upgrade pip + + - name: Install pypolychord + run: | + python -m pip install -v . + + - name: Import pypolychord + run: python -c "import pypolychord" + + - name: Hello world + run: python hello_world.py + + - name: Test pypolychord + run: | + python run_pypolychord.py + + # - name: Test pypolychord (MPI) + # run: mpirun -np 2 python run_pypolychord.py \ No newline at end of file diff --git a/.github/workflows/run_cmake.yaml b/.github/workflows/run_cmake.yaml deleted file mode 100644 index 76d7d94f..00000000 --- a/.github/workflows/run_cmake.yaml +++ /dev/null @@ -1,83 +0,0 @@ -# This workflow carries out the build of the package with CMake - -name: CMake build - -on: - push: - workflow_dispatch: - -jobs: - build-GNU: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install gfortran libopenmpi-dev cmake python3-dev pip - pip install scipy matplotlib getdist anesthetic ipython mpi4py - - - name: Run CMake - run: cmake -B build - - - name: Build - run: make -C build install - - - name: Test pypolychord - run: python run_pypolychord.py - - - name: Test pypolychord (MPI) - run: mpirun -np 2 python run_pypolychord.py - - build-Intel: - runs-on: ubuntu-latest - container: - image: intel/oneapi-hpckit - - steps: - - uses: actions/checkout@v2 - - - name: Run CMake - run: cmake -B build -DCMAKE_Fortran_COMPILER=ifort -DCMAKE_CXX_COMPILER=icpc - - - name: Build - run: make -C build install - - - name: Test pypolychord - run: python run_pypolychord.py - - - name: Test pypolychord (MPI) - run: mpirun -np 2 python run_pypolychord.py - - build-MacOS: - runs-on: macos-latest - strategy: - matrix: - cc: [ gcc, clang ] - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - brew install cmake gcc openmpi - pip3 install numpy scipy matplotlib getdist anesthetic ipython mpi4py - - - name: Run CMake - GCC - if: ${{ env.cc == 'gcc' }} - run: cmake -B build -DCMAKE_Fortran_COMPILER=gfortran-11 -DCMAKE_CXX_COMPILER=gcc-11 - - - name: Run CMake - AppleClang - if: ${{ env.cc == 'clang' }} - run: cmake -B build -DCMAKE_Fortran_COMPILER=gfortran-11 - - - name: Build - run: make -C build install - - - name: Test pypolychord - run: python run_pypolychord.py - - - name: Test pypolychord (MPI) - run: mpirun -np 2 python run_pypolychord.py \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c41d2ad..5bf64e91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,9 +82,10 @@ if (python) # The Compiled .so file ################################################################# + # PyPolyChord stuff message(STATUS "Enabling Python package build") - find_package(Python3 COMPONENTS Interpreter Development NumPy REQUIRED) + find_package(Python3 COMPONENTS Interpreter Development NumPy REQUIRED) # find out the suffix for the current python version EXECUTE_PROCESS( @@ -112,31 +113,5 @@ if (python) # place all outputs in one place install(TARGETS _pypolychord LIBRARY DESTINATION ${target_lib_dir}) - - ################################################################# - # The simple python module - ################################################################# - - set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup_cmake_template.py") - set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py") - set(DEPS "${CMAKE_CURRENT_SOURCE_DIR}/pypolychord/__init__.py") - set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp") # dummy target for dependence - - # fill in the variables of the setup.py file - configure_file(${SETUP_PY_IN} ${SETUP_PY}) - - # custom target - add_custom_command(OUTPUT ${OUTPUT} - COMMAND ${Python3_EXECUTABLE} ${SETUP_PY} build - COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT} - DEPENDS ${DEPS} _pypolychord) - add_custom_target(target ALL DEPENDS ${OUTPUT}) - - # installation with setup.py - if (python_user_install) - install(CODE "execute_process(COMMAND ${Python3_EXECUTABLE} ${SETUP_PY} install)") - else (python_user_install) - install(CODE "execute_process(COMMAND ${Python3_EXECUTABLE} ${SETUP_PY} install --user)") - endif (python_user_install) - + endif (python) diff --git a/Makefile_cray b/Makefile_cray index e3590b78..3456fe6c 100644 --- a/Makefile_cray +++ b/Makefile_cray @@ -10,13 +10,13 @@ LDSHARED = $(LD) -shared # Archive tool AR = ar rv -FFLAGS += -fpp -fpic -qopenmp -dynamic -CXXFLAGS += -fpic -qopenmp -dynamic +FFLAGS += -cpp -fpic -fopenmp -dynamic +CXXFLAGS += -fpic -fopenmp -dynamic CFLAGS += -fpic #setting for Edison/Cori on NERSC ifneq ($(NERSC_HOST),) -FFLAGS += -axMIC-AVX512,CORE-AVX2 -CXXFLAGS += -axMIC-AVX512,CORE-AVX2 +FFLAGS += -ffree-line-length-none -fallow-argument-mismatch +CXXFLAGS += -ffree-line-length-none -fallow-argument-mismatch endif ifdef IPO diff --git a/hello_world.py b/hello_world.py new file mode 100644 index 00000000..d837ae97 --- /dev/null +++ b/hello_world.py @@ -0,0 +1,57 @@ +print("hello world") +from scipy.special import erfinv +print("from numpy import pi, log, sqrt") +from numpy import pi, log, sqrt +print("import pypolychord") +import pypolychord +print("from pypolychord.settings import PolyChordSettings") +from pypolychord.settings import PolyChordSettings +print("from pypolychord.priors import UniformPrior") +from pypolychord.priors import UniformPrior +try: + from mpi4py import MPI +except ImportError: + pass + + +#| Define a four-dimensional spherical gaussian likelihood, +#| width sigma=0.1, centered on the 0 with one derived parameter. +#| The derived parameter is the squared radius + +nDims = 4 +nDerived = 1 +sigma = 0.1 + +def likelihood(theta): + """ Simple Gaussian Likelihood""" + + nDims = len(theta) + r2 = sum(theta**2) + logL = -log(2*pi*sigma*sigma)*nDims/2.0 + logL += -r2/2/sigma/sigma + + return logL, [r2] + +#| Define a box uniform prior from -1 to 1 + +def prior(hypercube): + """ Uniform prior from [-1,1]^D. """ + return UniformPrior(-1, 1)(hypercube) + +#| Optional dumper function giving run-time read access to +#| the live points, dead points, weights and evidences + +def dumper(live, dead, logweights, logZ, logZerr): + print("Last dead point:", dead[-1]) + +#| Initialise the settings +print("about to create settings") +settings = PolyChordSettings(nDims, nDerived) +settings.file_root = 'gaussian' +settings.nlive = 200 +settings.do_clustering = True +settings.read_resume = False + +#| Run PolyChord +print("about to run_pypolychord", flush=True) +output = pypolychord.run_polychord(likelihood, nDims, nDerived, settings, prior, dumper) \ No newline at end of file diff --git a/pypolychord/polychord.py b/pypolychord/polychord.py index 7df4fce3..580fba94 100644 --- a/pypolychord/polychord.py +++ b/pypolychord/polychord.py @@ -176,6 +176,9 @@ def wrap_loglikelihood(theta, phi): def wrap_prior(cube, theta): theta[:] = prior(cube) + settings.grade_dims = [int(d) for d in settings.grade_dims] + settings.nlives = {float(logL):int(nlive) for logL, nlive in settings.nlives.items()} + # Run polychord from module library _pypolychord.run(wrap_loglikelihood, wrap_prior, diff --git a/run_pypolychord.py b/run_pypolychord.py index 465c3543..ca5ba410 100755 --- a/run_pypolychord.py +++ b/run_pypolychord.py @@ -1,6 +1,10 @@ +print("from numpy import pi, log, sqrt") from numpy import pi, log, sqrt +print("import pypolychord") import pypolychord +print("from pypolychord.settings import PolyChordSettings") from pypolychord.settings import PolyChordSettings +print("from pypolychord.priors import UniformPrior") from pypolychord.priors import UniformPrior try: from mpi4py import MPI @@ -39,7 +43,7 @@ def dumper(live, dead, logweights, logZ, logZerr): print("Last dead point:", dead[-1]) #| Initialise the settings - +print("about to create settings") settings = PolyChordSettings(nDims, nDerived) settings.file_root = 'gaussian' settings.nlive = 200 @@ -47,7 +51,7 @@ def dumper(live, dead, logweights, logZ, logZerr): settings.read_resume = False #| Run PolyChord - +print("about to run_pypolychord") output = pypolychord.run_polychord(likelihood, nDims, nDerived, settings, prior, dumper) #| Create a paramnames file diff --git a/setup.py b/setup.py index 46a2bf51..093f6fff 100644 --- a/setup.py +++ b/setup.py @@ -92,13 +92,38 @@ def build_extension(self, ext) -> None: def build_cmake(self, ext): print(self.build_temp) - cwd = pathlib.Path().absolute() + cwd = pathlib.Path().cwd() build_temp = pathlib.Path(self.build_temp) build_temp.mkdir(parents=True, exist_ok=True) + # os.chdir(str(build_temp)) + # self.spawn(["cmake", str(cwd), f"-DPython3_EXECUTABLE={sys.executable}"]) + # self.spawn(["make"]) + env = {} + env["PATH"] = os.environ["PATH"] + if self.distribution.no_mpi is None: + env["MPI"] = "1" + # These need to be set so that build_ext uses the right compilers + cc_compiler = subprocess.check_output(["make", "print_CC"]).decode('utf-8').strip() + os.environ["CC"] = cc_compiler + + cxx_compiler = subprocess.check_output(["make", "print_CXX"]).decode('utf-8').strip() + os.environ["CXX"] = cxx_compiler + else: + env["MPI"] = "0" + + if self.distribution.debug_flags is not None: + self.distribution.ext_modules[0].extra_compile_args += ["-g", "-O0"] + env["DEBUG"] = "1" + + # BASE_PATH = os.path.dirname(os.path.abspath(__file__)) os.chdir(str(build_temp)) - self.spawn(["cmake", str(cwd)]) - self.spawn(["make"]) + print("managed to change directory") + env["PWD"] = str(build_temp) + env.update({k : os.environ[k] for k in ["CC", "CXX", "FC"] if k in os.environ}) + subprocess.check_call(["cmake", str(cwd), f"-DPython3_EXECUTABLE={sys.executable}"], env=env) #, cwd=str(build_temp)) + print("cmade") + subprocess.check_call(["make", "-e"], env=env) #, cwd=str(build_temp)) os.chdir(cwd) class DistributionWithOption(Distribution, object): diff --git a/setup_cmake_template.py b/setup_cmake_template.py deleted file mode 100644 index 3f53d913..00000000 --- a/setup_cmake_template.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -Template for setup.py that should be populated by CMake with: -configure_file(${SETUP_PY_IN} ${SETUP_PY}) - -Used template variables: - - "target_python_so" : place where _pypolychord.ARCH.so is built (NOT install path) - - "PACKAGE_VERSION" : version of the package - - "CMAKE_CURRENT_SOURCE_DIR": root directory, where a standard setup.py would be placed -""" - -import os -import shutil -import sys -from distutils.core import setup - -from setuptools import Extension -from setuptools.command.build_ext import build_ext - - -def readme(): - with open('${CMAKE_CURRENT_SOURCE_DIR}/README.rst') as f: - return f.read() - - -def get_version(short=False): - with open('${CMAKE_CURRENT_SOURCE_DIR}/src/polychord/feedback.f90') as f: - for line in f: - if 'version' in line: - return line[44:50] - - -class MyBuildExtension(build_ext): - """This class 'builds' the extension module, by - copying it from the place where CMake placed it. - """ - - def build_extension(self, ext): - - # _pypolychord.ARCH.so - if os.path.exists("${target_python_so}"): - shutil.copyfile("${target_python_so}", self.get_ext_fullpath(ext.name)) - elif sys.argv[2] == "install": - # let's warn here, though this should not happen with the current CMake setup - print("NOT FOUND: ${target_python_so}\nYour installation may be incomplete.") - - -setup(name='pypolychord', - description='Python interface to PolyChord ${PACKAGE_VERSION}', - long_description=readme(), - long_description_content_type='text/x-rst', - url='https://ccpforge.cse.rl.ac.uk/gf/project/polychord/', - author='Will Handley', - author_email='wh260@cam.ac.uk', - license='PolyChord', - install_requires=['numpy', 'scipy'], - extras_require={'plotting': 'getdist'}, - - classifiers=[ - "Development Status :: 5 - Production/Stable", - - "Intended Audience :: Education", - - "Operating System :: MacOS :: MacOS X", - "Operating System :: Unix", - - "Topic :: Scientific/Engineering :: Astronomy", - "Topic :: Scientific/Engineering :: Physics", - - "Programming Language :: C++", - "Programming Language :: Fortran", - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - "Programming Language :: Python :: 3.10", - - ], - - # Don't touch anything below here - CMake fills this in - version=get_version(), - package_dir={'pypolychord': '${CMAKE_CURRENT_SOURCE_DIR}/pypolychord'}, - packages=['pypolychord'], - cmdclass={'build_ext': MyBuildExtension}, - ext_modules=[Extension('_pypolychord', [])], - ) diff --git a/src/polychord/ini.f90 b/src/polychord/ini.f90 index 9a78af70..ea60f382 100644 --- a/src/polychord/ini.f90 +++ b/src/polychord/ini.f90 @@ -226,7 +226,6 @@ function get_string(file_name,key_word,dflt,ith) end function get_string function get_double(file_name,key_word,dflt) - use utils_module, only: STR_LENGTH use abort_module, only: halt_program character(len=*),intent(in) :: file_name !> The name of the file to search in character(len=*),intent(in) :: key_word !> keyword to search for @@ -247,7 +246,6 @@ function get_double(file_name,key_word,dflt) end function get_double subroutine get_doubles(file_name,key_word,doubles) - use utils_module, only: STR_LENGTH use array_module, only: reallocate character(len=*),intent(in) :: file_name !> The name of the file to search in character(len=*),intent(in) :: key_word !> keyword to search for @@ -274,7 +272,6 @@ subroutine get_doubles(file_name,key_word,doubles) end subroutine get_doubles subroutine get_integers(file_name,key_word,integers) - use utils_module, only: STR_LENGTH use array_module, only: reallocate character(len=*),intent(in) :: file_name !> The name of the file to search in character(len=*),intent(in) :: key_word !> keyword to search for @@ -301,7 +298,6 @@ subroutine get_integers(file_name,key_word,integers) end subroutine get_integers function get_integer(file_name,key_word,dflt) - use utils_module, only: STR_LENGTH use abort_module, only: halt_program character(len=*),intent(in) :: file_name !> The name of the file to search in character(len=*),intent(in) :: key_word !> keyword to search for @@ -324,7 +320,6 @@ function get_integer(file_name,key_word,dflt) end function get_integer function get_logical(file_name,key_word,dflt) - use utils_module, only: STR_LENGTH use abort_module, only: halt_program character(len=*),intent(in) :: file_name !> The name of the file to search in character(len=*),intent(in) :: key_word !> keyword to search for @@ -467,7 +462,6 @@ end subroutine get_params subroutine next_element(line_buffer,delimiter) - use utils_module, only: STR_LENGTH implicit none character(len=:), allocatable, intent(inout) :: line_buffer ! Line buffer character :: delimiter @@ -475,7 +469,6 @@ subroutine next_element(line_buffer,delimiter) end subroutine next_element subroutine get_prior_params(prior_params,line_buffer) - use utils_module, only: STR_LENGTH implicit none character(len=:), allocatable,intent(inout) :: line_buffer ! Line buffer real(dp),allocatable,dimension(:),intent(out) :: prior_params ! prior parameters diff --git a/src/polychord/maximiser.F90 b/src/polychord/maximiser.F90 index cdf18fa7..f2990220 100644 --- a/src/polychord/maximiser.F90 +++ b/src/polychord/maximiser.F90 @@ -64,7 +64,7 @@ end subroutine maximise function do_maximisation(loglikelihood,prior,settings,RTI, posterior) result(max_point) use calculate_module, only: calculate_point - use utils_module, only: stdout_unit, fmt_len, sort_doubles + use utils_module, only: sort_doubles use settings_module, only: program_settings use run_time_module, only: run_time_info use read_write_module, only: write_max_file, mean @@ -100,10 +100,10 @@ function prior(cube) result(theta) real(dp) :: max_loglike - integer :: imax, cluster_id + integer :: cluster_id real(dp), dimension(settings%nTotal) :: max_point integer :: nlike, j - real(dp), dimension(settings%nDims) :: xl, xu, x + real(dp), dimension(settings%nDims) :: x real(dp), dimension(settings%nDims,settings%nDims+1) :: simplex real(dp), dimension(settings%nDims+1) :: f real(dp), dimension(settings%nlive) :: l diff --git a/src/polychord/nelder_mead.f90 b/src/polychord/nelder_mead.f90 index 0477c1e7..b7123ba3 100644 --- a/src/polychord/nelder_mead.f90 +++ b/src/polychord/nelder_mead.f90 @@ -24,7 +24,6 @@ function func(x) integer :: n, j integer, dimension(size(f)) :: i double precision, dimension(size(f)-1) :: xo, xr, xe, xc, xmax - double precision, dimension(size(f)-1,size(f)-1) :: V double precision :: fr, fe, fc double precision :: det0, det1 diff --git a/src/polychord/read_write.F90 b/src/polychord/read_write.F90 index 49777865..5a4cc913 100644 --- a/src/polychord/read_write.F90 +++ b/src/polychord/read_write.F90 @@ -1002,8 +1002,6 @@ subroutine write_properties_file(settings) type(program_settings),intent(in) :: settings !> Program settings - integer :: i - call check_directories(settings) open(unit=properties_unit,file=trim(properties_file(settings)))