Skip to content

Commit

Permalink
Merge pull request #202 from SNLComputation/python_to_pybind11
Browse files Browse the repository at this point in the history
Switch from SWIG to pybind11 for Python interface and compadre->pycompadre
  • Loading branch information
kuberry committed Jun 3, 2020
2 parents 4efddb4 + 6497372 commit 15d1ca6
Show file tree
Hide file tree
Showing 217 changed files with 42,532 additions and 8,415 deletions.
93 changes: 14 additions & 79 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,18 @@ else() # Raw CMake Project
# RPATH should always include the folder it is called from
bob_option(PYTHON_CALLING_BUILD "Python setuptools calling build" OFF)
bob_option(Compadre_USE_PYTHON "Use PYTHON" OFF)
bob_option(Compadre_USE_MATLAB "Use MATLAB interface for PYTHON" OFF)
set(PYTHON_LIBRARY_PREFIX "..") # relative to examples folder
if (Compadre_USE_PYTHON)
bob_input(PYTHON_EXECUTABLE "" PATH "Python executable location")
IF(NOT(PYTHON_EXECUTABLE))
MESSAGE(STATUS "Python executable location PYTHON_EXECUTABLE not given. Search made using 'which python'")
EXECUTE_PROCESS(
COMMAND which "python"
OUTPUT_VARIABLE PYTHON_EXECUTABLE
OUTPUT_STRIP_TRAILING_WHITESPACE )
ENDIF()
MESSAGE(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}")
if (APPLE)
SET(CMAKE_BUILD_RPATH ${CMAKE_BUILD_RPATH} "@loader_path/")
SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} "@loader_path/")
Expand Down Expand Up @@ -380,84 +391,6 @@ else() # Raw CMake Project



#PYTHON
bob_option(Compadre_USE_MATLAB "Use MATLAB interface for PYTHON" OFF)
bob_input(PYTHON_PREFIX "" PATH "Path to PYTHON install")
if (PYTHON_PREFIX)
set(CMAKE_PREFIX_PATH ${PYTHON_PREFIX} ${CMAKE_PREFIX_PATH})
endif()
if (Compadre_USE_PYTHON)

bob_input(PYTHON_EXECUTABLE "" PATH "Python executable location")
IF(NOT(PYTHON_EXECUTABLE))
MESSAGE(STATUS "Python executable location PYTHON_EXECUTABLE not given. Search made using 'which python'")
EXECUTE_PROCESS(
COMMAND which "python"
OUTPUT_VARIABLE PYTHON_EXECUTABLE
OUTPUT_STRIP_TRAILING_WHITESPACE )
ENDIF()
MESSAGE(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}")

EXECUTE_PROCESS(
COMMAND "${PYTHON_EXECUTABLE}" -c "import site; print(site.USER_SITE)"
OUTPUT_VARIABLE PYTHON_SITEPACKAGES
OUTPUT_STRIP_TRAILING_WHITESPACE )

IF(NOT EXISTS ${PYTHON_SITEPACKAGES})
EXECUTE_PROCESS(
COMMAND "${PYTHON_EXECUTABLE}" -c "import sysconfig; print(sysconfig.get_path('platlib'))"
OUTPUT_VARIABLE PYTHON_SITEPACKAGES
OUTPUT_STRIP_TRAILING_WHITESPACE )
ENDIF()
MESSAGE(STATUS "PYTHON_SITEPACKAGES: ${PYTHON_SITEPACKAGES}")

IF(NOT EXISTS ${Numpy_PREFIX})
EXECUTE_PROCESS(
COMMAND "${PYTHON_EXECUTABLE}" -c "import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE Numpy_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE )
ENDIF()
MESSAGE(STATUS "Numpy_PREFIX: ${Numpy_PREFIX}")

FIND_PATH(Numpy_INCLUDE_DIRS numpy/arrayobject.h HINTS ${Numpy_PREFIX})
IF (Numpy_INCLUDE_DIRS)
MESSAGE(STATUS "Numpy_INCLUDE_DIRS: ${Numpy_INCLUDE_DIRS}")
ELSE()
MESSAGE(FATAL_ERROR "Numpy headers not found, but needed when Compadre_USE_PYTHON:BOOL=ON. Try setting Numpy_PREFIX.")
ENDIF()

set(SWIG_PREFIX "../python") # relative to examples folder
bob_input(GMLS_Module_DEST "${CMAKE_INSTALL_LIBDIR}/python/dist-packages" PATH "Path to install python module")

IF(NOT EXISTS ${PYTHON_INCLUDE_DIRS})
EXECUTE_PROCESS(
COMMAND "${PYTHON_EXECUTABLE}" -c "from distutils.sysconfig import get_python_inc; print(get_python_inc())"
OUTPUT_VARIABLE PYTHON_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE )
ENDIF()

EXECUTE_PROCESS(
COMMAND "${PYTHON_EXECUTABLE}" -c "from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"))"
OUTPUT_VARIABLE PYTHON_PATHS
OUTPUT_STRIP_TRAILING_WHITESPACE )
MESSAGE(STATUS "PYTHON_PATHS: ${PYTHON_PATHS}")

file(GLOB PYTHON_LIBNAME
"${PYTHON_PATHS}/libpython*${CMAKE_SHARED_LIBRARY_SUFFIX}"
)
get_filename_component(PYTHON_LIBNAME_BASE "${PYTHON_LIBNAME}" NAME)
STRING(REGEX REPLACE "lib(.*)${CMAKE_SHARED_LIBRARY_SUFFIX}" "\\1" PYTHON_LIBNAME "${PYTHON_LIBNAME_BASE}")

MESSAGE(STATUS "PYTHON_LIBNAME: ${PYTHON_LIBNAME}")
find_library(PYTHON_LIBRARIES NAME "${PYTHON_LIBNAME}" PATHS "${PYTHON_PATHS}" NO_DEFAULT_PATH)

MESSAGE(STATUS "PYTHON_INCLUDE_DIRS: ${PYTHON_INCLUDE_DIRS}")
MESSAGE(STATUS "PYTHON_LIBRARIES: ${PYTHON_LIBRARIES}")

endif()



##########
#
#
Expand Down Expand Up @@ -551,7 +484,9 @@ else() # Raw CMake Project
endif()

if(Compadre_USE_PYTHON)
add_subdirectory(python)
add_subdirectory(pycompadre/pybind11)
pybind11_add_module(pycompadre pycompadre/pycompadre.cpp)
target_link_libraries(pycompadre PUBLIC compadre)
endif()


Expand Down
6 changes: 6 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include *
recursive-include * *
prune .git
prune .eggs
prune build
prune dist
2 changes: 1 addition & 1 deletion cmake/Compadre_Version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.3
1.0.7
33 changes: 19 additions & 14 deletions examples/Python_3D_Convergence.py.in
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import sys

# installation folder
gmls_python_installation_path = "@SWIG_PREFIX@"
gmls_python_installation_path = "@PYTHON_LIBRARY_PREFIX@"
sys.path.append(gmls_python_installation_path)

import GMLS_Module
import pycompadre

# import other relevant models
import numpy as np
Expand Down Expand Up @@ -46,8 +46,8 @@ def test1(ND):
dimensions = 3

# initialize 3rd order reconstruction using 2nd order basis in 3D (GMLS)
gmls_obj=GMLS_Module.GMLS_Python(polyOrder, "QR", manifoldPolyOrder, dimensions)
gmls_obj.setWeightingOrder(10)
gmls_obj=pycompadre.GMLS(polyOrder, dimensions, "QR", "STANDARD")
gmls_obj.setWeightingPower(10)
gmls_obj.setWeightingType("power")

NT = 100 # Targets
Expand Down Expand Up @@ -85,18 +85,23 @@ def test1(ND):

# neighbor search
epsilon_multiplier = 1.5
gmls_obj.generateKDTree(source_sites)
gmls_obj.generateNeighborListsFromKNNSearchAndSet(target_sites, polyOrder, dimensions, epsilon_multiplier)
gmls_helper = pycompadre.ParticleHelper(gmls_obj)
gmls_helper.generateKDTree(source_sites)
gmls_helper.generateNeighborListsFromKNNSearchAndSet(target_sites, polyOrder, dimensions, epsilon_multiplier)

# set data in gmls object
gmls_obj.setSourceSites(source_sites)
gmls_helper.setSourceSites(source_sites)

# used in combination with polynomial coefficients
epsilons = gmls_obj.getWindowSizes()
epsilons = gmls_helper.getWindowSizes()

gmls_obj.addTargets(pycompadre.TargetOperation.ScalarPointEvaluation)
gmls_obj.addTargets(pycompadre.TargetOperation.PartialXOfScalarPointEvaluation)
(dimensions>1) and gmls_obj.addTargets(pycompadre.TargetOperation.PartialYOfScalarPointEvaluation)
(dimensions>2) and gmls_obj.addTargets(pycompadre.TargetOperation.PartialYOfScalarPointEvaluation)

# generate stencil with number of batches set to 1, and keeping coefficients (not necessary)
gmls_obj.generatePointEvaluationStencil(1, True)
gmls_obj.generateAlphas(1, True)


# create sample data at source sites
Expand All @@ -106,15 +111,15 @@ def test1(ND):
data_vector = np.array(data_vector, dtype=np.dtype('d'))

# apply stencil to sample data for all targets
computed_answer = gmls_obj.applyStencil(data_vector)
computed_answer = gmls_helper.applyStencil(data_vector, pycompadre.TargetOperation.ScalarPointEvaluation)

l2_error = 0
for i in range(NT):
l2_error += np.power(abs(computed_answer[i] - sinxsinysinz(target_sites[i])),2)
l2_error = math.sqrt(l2_error/float(NT))

# get polynomial coefficients
polynomial_coefficients = gmls_obj.getPolynomialCoefficients(data_vector)
polynomial_coefficients = gmls_helper.getPolynomialCoefficients(data_vector)

# alternative way to compute h1 semi norm
# could remap using the gradient operator, but instead this uses calculated polynomial coefficients and applies
Expand All @@ -130,9 +135,9 @@ def test1(ND):

return (l2_error, h1_seminorm_error)

kokkos_obj=GMLS_Module.Kokkos_Python(int(args.kokkos_threads), int(args.kokkos_numa),
int(args.kokkos_device), int(args.kokkos_ngpus),
True) # print state after initializing
kokkos_obj=pycompadre.KokkosParser(int(args.kokkos_threads), int(args.kokkos_numa),
int(args.kokkos_device), int(args.kokkos_ngpus),
True) # print state after initializing

# of points in each dimension to run the test over
ND = [5, 10, 20, 40]
Expand Down
File renamed without changes.
7 changes: 7 additions & 0 deletions pycompadre/build.sh.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
echo "Compadre_USE_MPI:BOOL=OFF" > $RECIPE_DIR/cmake_opts.txt
echo "PYTHON_EXECUTABLE=$PYTHON" >> $RECIPE_DIR/cmake_opts.txt
if [ "$OSX_ARCH" != "" ]; then
echo "BLAS_LIBRARY_DIRS=/System/Library/Frameworks/Accelerate.framework//Versions/A/Frameworks/vecLib.framework/Versions/A/" >> $RECIPE_DIR/cmake_opts.txt
echo "LAPACK_LIBRARY_DIRS=/System/Library/Frameworks/Accelerate.framework//Versions/A/Frameworks/vecLib.framework/Versions/A/" >> $RECIPE_DIR/cmake_opts.txt
fi
CMAKE_CONFIG_FILE=$RECIPE_DIR/cmake_opts.txt $PYTHON setup.py install
1 change: 1 addition & 0 deletions pycompadre/cmake_opts.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Compadre_USE_MPI:BOOL=OFF
File renamed without changes.
10 changes: 10 additions & 0 deletions pycompadre/insert_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import re
import sys

assert len(sys.argv) > 1, "Input argument for version missing."
if (len(sys.argv) > 1):
version = str(sys.argv[1])

with open ('../cmake/Compadre_Version.txt', 'w' ) as f:
f.write(version)

129 changes: 129 additions & 0 deletions pycompadre/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/bin/bash

# if looking to install the package, just run 'pip install .' from the root directory of the repo.

# for creating a pypi package, run:
# >> python setup.py sdist
# >> twine upload dist/*

#
# This file handles installation and packaging of the python interface for the Compadre Toolkit
# Execute this file with a -i or --install flag and it will build and install this package
#

for i in "$@"
do
case $i in
-e=*|--executable=*)
EXECUTABLE="${i#*=}"
shift # passed argument=value
;;
-c|--clean)
CLEAN=YES
shift # passed argument with no value
;;
-p|--package)
PACKAGE=YES
shift # passed argument with no value
;;
-P|--PACKAGE)
PACKAGE=YES
shift # passed argument with no value
;;
-C|--conda)
CONDA=YES
shift # passed argument with no value
;;
-h|--help)
HELP=YES
shift # passed argument with no value
;;
*)
# unknown option
;;
esac
done

# install the python package of compadre for the user
if [ "$HELP" == "YES" ]; then

echo "-e | --executable Python executable to be used for package installation"
echo "-c | --clean Removes temporary files created by packaging and installation"
echo "-p | --package Create a python package that can be uploaded to Pypi"
echo "-h | --help See the help screen that you are currently reading"
echo "-v= | --version= (OPTIONAL UNLESS PACKAGING)"
exit 0

fi

# remove temporary files created by install and packaging
if [ "$CLEAN" == "YES" ]; then
rm -r ../dist
rm -r ../pycompadre.egg-info
exit 0
fi

# output variables used
echo "CONDA: ${CONDA}"
if [ "$EXECUTABLE" == "" ]; then
EXECUTABLE=`which python`
echo "$0: No Python executable provided with \" -e=*\", so first python found in search path is used: $EXECUTABLE"
fi
echo "PYTHON EXECUTABLE: ${EXECUTABLE}"

# (NOT for users) create a python package that can be uploaded to pypi
if [ "$PACKAGE" == "YES" ]; then


rm -rf ../dist
rm -rf ../build
rm -rf ../meta.yaml
rm -rf ../build.sh
rm -rf ../pycompadre.egg-info
cp cmake_opts.txt ..

cd ..

CMAKE_CONFIG_FILE=cmake_opts.txt $EXECUTABLE setup.py bdist_wheel sdist
echo "bdist_wheel and sdist complete."

cd pycompadre
# follow up with twine upload ../dist/*

fi

# (NOT for users) create a conda package
if [ "$CONDA" == "YES" ]; then

# conda activate builder
# conda build purge-all
# conda-bld should be cleared as well


rm -rf ../dist
rm -rf ../build
rm -rf ../meta.yaml
rm -rf ../build.sh
rm -rf ../pycompadre.egg-info
cp cmake_opts.txt ..

#cp update_conda_cmake.py ../update_conda_cmake.py
# named *.in so that they are not picked up by conda in the pycompadre folder
cp meta.yaml.in ../meta.yaml
cp build.sh.in ../build.sh
#cp conda_build_config.yaml.in ../conda_build_config.yaml
cd ..
conda-build . --python=2.7 --python=3.5 --python=3.6 --python=3.7 --python=3.8
#--python=3.5
#--python=3.7
# --python=3.6 --python=3.7
cd pycompadre

fi

# instructions for updating conda package
# 1.) git fetch origin on compadre repo
# 2.) from the root of the repo, with master checked out, run >> git merge origin/conda_files --allow-unrelated-histories
# 3.) >> conda-build . --python=3.6 --python=3.7 --python=3.8
# 4.) >> anaconda login
# 5.) >> anaconda upload /some/path/to/compadre.tar.bz2

0 comments on commit 15d1ca6

Please sign in to comment.