Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MPI VAMPyR #83

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ include(${PROJECT_SOURCE_DIR}/cmake/downloaded/autocmake_safeguards.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/downloaded/autocmake_code_coverage.cmake)

find_package(Python 3.7 REQUIRED COMPONENTS Interpreter Development)
# find MPI and mpi4py
include(${PROJECT_SOURCE_DIR}/cmake/custom/mpi.cmake)
# download pybind11 if not available on the system
include(${PROJECT_SOURCE_DIR}/cmake/custom/fetch_pybind11.cmake)
# download MRCPP if not available on the system
Expand Down
92 changes: 92 additions & 0 deletions cmake/custom/FindPythonModule.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Downloaded from
# http://www.cmake.org/pipermail/cmake/2011-January/041666.html
# * Added FORCE to location var
# * Function to macro so module_FOUND shows up
# * Remove ``if(NOT PY_${module})`` so runs each time, also remove module caps
# * Module name, not path in fphsa
# * Added version handling via parse_version call

#.rst:
#
# Find if a Python module is installed.
# Usage: find_python_module(<package> [[ATLEAST | EXACT] version] [QUIET] [REQUIRED])

macro(find_python_module module)
cmake_parse_arguments(ARG
"QUIET;REQUIRED" # options
"ATLEAST;EXACT" # one-value arguments
"" # multi-value arguments
${ARGN} # everything else
)

if(ARG_QUIET)
set(${module}_FIND_QUIETLY TRUE)
endif()

if(ARG_REQUIRED)
set(${module}_FIND_REQUIRED TRUE)
endif()

if(ARG_ATLEAST AND ARG_EXACT)
message(FATAL_ERROR "Can't be both ATLEAST and EXACT")
endif()
if(ARG_ATLEAST)
set(_op ">=")
set(${module}_tgtver ${ARG_ATLEAST})
elseif(ARG_EXACT)
set(_op "==")
set(${module}_tgtver ${ARG_EXACT})
else()
# deceive handle_standard_arguments into not caring about version
set(_${module}_requested_version_found "${Python_EXECUTABLE}")
endif()

unset(PY_${module} CACHE)
unset(${module}_VERSION CACHE)

execute_process(
COMMAND "${Python_EXECUTABLE}" "-c"
"import re; \
import ${module}; \
print(re.compile('/__init__.py.*').sub('', ${module}.__file__))"
RESULT_VARIABLE _${module}_status
OUTPUT_VARIABLE _${module}_location
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT ${_${module}_status})
set(PY_${module} ${_${module}_location} CACHE STRING "Location of Python module ${module}" FORCE)
execute_process(
COMMAND "${Python_EXECUTABLE}" "-c"
"import sys; \
import ${module}; \
print(${module}.__version__)"
RESULT_VARIABLE _${module}_ver_status
OUTPUT_VARIABLE _${module}_version
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT ${_${module}_ver_status})
set(${module}_VERSION ${_${module}_version} CACHE STRING
"Version of Python module ${module}" FORCE)

if(${module}_tgtver)
execute_process(
COMMAND "${Python_EXECUTABLE}" "-c"
"from pkg_resources import parse_version; \
print(parse_version('${${module}_VERSION}') ${_op} parse_version('${${module}_tgtver}'))"
RESULT_VARIABLE _${module}_verenuf_status
OUTPUT_VARIABLE _${module}_verenuf
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT ${_${module}_verenuf_status})
if(${_${module}_verenuf} STREQUAL "True")
set(_${module}_requested_version_found "${Python_EXECUTABLE}")
endif()
endif()
endif()
endif()
endif()
find_package_handle_standard_args(${module} DEFAULT_MSG PY_${module} _${module}_requested_version_found)
endmacro()
16 changes: 14 additions & 2 deletions cmake/custom/fetch_mrcpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,19 @@ set(MRCPP_FETCHED FALSE)

if(TARGET MRCPP::mrcpp)
get_property(_loc TARGET MRCPP::mrcpp PROPERTY LOCATION)
message(STATUS "Found MRCPP: ${_loc} (found version ${MRCPP_VERSION})")

get_target_property(MRCPP_HAS_OMP MRCPP::mrcpp MRCPP_HAS_OMP)
get_target_property(MRCPP_HAS_MPI MRCPP::mrcpp MRCPP_HAS_MPI)

message(STATUS "Found MRCPP (OpenMP: ${MRCPP_HAS_OMP}; MPI: ${MRCPP_HAS_MPI}): ${_loc} (found version ${MRCPP_VERSION})")

if(NOT MRCPP_HAS_OMP)
message(FATAL_ERROR "VAMPyR needs MRCPP with OpenMP features enabled!")
endif()

if(NOT MRCPP_HAS_MPI AND VAMPYR_WITH_MPI)
message(FATAL_ERROR "You enabled MPI for VAMPyR, but MRCPP does not have MPI features enabled!")
endif()
else()
message(STATUS "Suitable MRCPP could not be located. Fetching and building!")
include(FetchContent)
Expand All @@ -24,7 +36,7 @@ else()
set(CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER})
# Always build with OpenMP and without MPI
set(ENABLE_OPENMP TRUE CACHE BOOL "")
set(ENABLE_MPI FALSE CACHE BOOL "")
set(ENABLE_MPI ${VAMPYR_WITH_MPI} CACHE BOOL "")
set(ENABLE_TESTS FALSE CACHE BOOL "")
set(ENABLE_EXAMPLES FALSE CACHE BOOL "")

Expand Down
64 changes: 64 additions & 0 deletions cmake/custom/mpi.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#.rst:
#
# Enables MPI support.
# This was adapted from Autocmake
#
# Variables used::
#
# VAMPYR_WITH_MPI
#
# autocmake.yml configuration::
#
# docopt: "--mpi Enable MPI parallelization [default: False]."
# define: "'-DVAMPYR_WITH_MPI={0}'.format(arguments['--mpi'])"

option(VAMPYR_WITH_MPI "Enable MPI parallelization" OFF)

if(VAMPYR_WITH_MPI)
find_package(MPI REQUIRED COMPONENTS CXX)

if(NOT TARGET MPI::MPI_CXX)
message(FATAL_ERROR "MPI-enabled VAMPyR requires a working MPI installation.")
endif()

# find mpi4py
include(${PROJECT_SOURCE_DIR}/cmake/custom/FindPythonModule.cmake)

find_python_module(mpi4py REQUIRED)

# we also need the include directories for mpi4py
if(mpi4py_FOUND)
execute_process(
COMMAND
"${Python_EXECUTABLE}" "-c"
"import mpi4py as m; print(m.__version__); print(m.get_include());"
RESULT_VARIABLE
_mpi4py_SEARCH_SUCCESS
OUTPUT_VARIABLE
_mpi4py_VALUES
ERROR_VARIABLE
_mpi4py_ERROR_VALUE
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Convert the process output into a list
string(REGEX REPLACE ";" "\\\\;" _mpi4py_VALUES ${_mpi4py_VALUES})
string(REGEX REPLACE "\n" ";" _mpi4py_VALUES ${_mpi4py_VALUES})
list(GET _mpi4py_VALUES 0 mpi4py_VERSION)
list(GET _mpi4py_VALUES 1 mpi4py_INCLUDE_DIRS)

# Make sure all directory separators are '/'
string(REGEX REPLACE "\\\\" "/" mpi4py_INCLUDE_DIRS ${mpi4py_INCLUDE_DIRS})

# Get the major and minor version numbers
string(REGEX REPLACE "\\." ";" _mpi4py_VERSION_LIST ${mpi4py_VERSION})
list(GET _mpi4py_VERSION_LIST 0 mpi4py_VERSION_MAJOR)
list(GET _mpi4py_VERSION_LIST 1 mpi4py_VERSION_MINOR)
list(GET _mpi4py_VERSION_LIST 2 mpi4py_VERSION_PATCH)
string(REGEX MATCH "[0-9]*" mpi4py_VERSION_PATCH ${mpi4py_VERSION_PATCH})
math(EXPR mpi4py_VERSION_DECIMAL
"(${mpi4py_VERSION_MAJOR} * 10000) + (${mpi4py_VERSION_MINOR} * 100) + ${mpi4py_VERSION_PATCH}")
else()
message(FATAL_ERROR "MPI-enabled VAMPyR requires a working mpi4py installation.")
endif()
endif()
20 changes: 10 additions & 10 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 5 additions & 6 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
flake = false;
};
mach-nix = {
url = "mach-nix/3.4.0";
url = "mach-nix/3.5.0";
inputs.pypi-deps-db.follows = "pypi-deps-db";
};
};
Expand All @@ -21,22 +21,21 @@
requirements = builtins.readFile ./requirements.txt + ''
# additional dependencies for local work
#jupyterlab
pre-commit
pre-commit
'';
};
in
{
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
buildInputs = with pkgs; [
cmake
eigen
gcc
openmpi
ninja
];
buildInputs = [
openmpi
pythonEnv
];
hardeningDisable = [ "all" ];
NINJA_STATUS = "[Built edge %f of %t in %e sec] ";
};
});
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ norecursedirs = [

[build-system]
requires = [
"mpi4py>=3.0",
"pybind11[global]>=2.6",
"setuptools>=46.4.0",
"wheel",
"scikit-build>=0.13",
"cmake>=3.17",
"ninja; platform_system!='Windows'",
]

build-backend = "setuptools.build_meta"
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
numpy
mpi4py>=3.0,<3.1.0
pytest
pybind11[global]
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ setup_requires =
ninja; platform_system!='Windows'

install_requires =
#mpi4py >= 3.0
numpy >= 1.15.0
mpi4py >= 3.0

test_suite =
tests
Expand All @@ -44,6 +43,7 @@ docs =
sphinx_rtd_theme

test =
numpy >= 1.15.0
pytest
pytest-cov

Expand Down
3 changes: 3 additions & 0 deletions src/vampyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ target_compile_definitions(_vampyr
target_include_directories(_vampyr
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
SYSTEM PRIVATE
${mpi4py_INCLUDE_DIRS}
)

target_link_libraries(_vampyr
PUBLIC
MRCPP::mrcpp
$<BUILD_INTERFACE:$<$<TARGET_EXISTS:MPI::MPI_CXX>:MPI::MPI_CXX>>
)

# handle RPATH
Expand Down
Loading