Commit 6619da9c authored by Chris Cantwell's avatar Chris Cantwell

Merge branch 'master' into feature/ProcessRemoveField

parents d2930994 0eb52c10
Pipeline #465 passed with stage
in 0 seconds
......@@ -90,6 +90,7 @@ v5.0.0
- Fix manifold face curvature nodes (!913)
- Fix writing 1D surfaces (!930)
- Fix surface string parsin in BL splitting (!937)
- Fix issue with MLSC after Scotch conversion (!943)
- Add support for Gmsh 4.0 mesh file format (!964)
**FieldConvert**:
......
......@@ -142,6 +142,7 @@ OPTION(NEKTAR_BUILD_UTILITIES "Build utilities." ON)
OPTION(NEKTAR_BUILD_UNIT_TESTS "Build unit tests." ON)
OPTION(NEKTAR_BUILD_TESTS "Build regression tests." ON)
OPTION(NEKTAR_BUILD_TIMINGS "Build benchmark timing codes." OFF)
OPTION(NEKTAR_BUILD_PYTHON "Build Nektar++ Python bindings" OFF)
OPTION(NEKTAR_BUILD_PACKAGES "Build Nektar++ binary packages" OFF)
MARK_AS_ADVANCED(NEKTAR_BUILD_PACKAGES)
......@@ -206,6 +207,7 @@ INCLUDE (ThirdPartyHDF5)
INCLUDE (ThirdPartyScotch)
INCLUDE (ThirdPartyZlib)
INCLUDE (ThirdPartyBoost)
INCLUDE (ThirdPartyPython)
INCLUDE (ThirdPartyFFTW)
INCLUDE (ThirdPartyArpack)
INCLUDE (ThirdPartyMPI)
......
......@@ -27,7 +27,14 @@ set(PETSC_VALID_COMPONENTS
CXX)
if(NOT PETSc_FIND_COMPONENTS)
set(PETSC_LANGUAGE_BINDINGS "C")
get_property (_enabled_langs GLOBAL PROPERTY ENABLED_LANGUAGES)
list(FIND _enabled_langs "C" _index)
if (${_index} EQUAL -1)
set(PETSC_LANGUAGE_BINDINGS "CXX")
else()
set(PETSC_LANGUAGE_BINDINGS "C")
endif ()
else()
# Right now, this is designed for compatability with the --with-clanguage option, so
# only allow one item in the components list.
......@@ -58,25 +65,31 @@ function (petsc_get_version)
set (${var} ${val}) # Also in local scope so we have access below
endforeach ()
if (PETSC_VERSION_RELEASE)
set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" PARENT_SCOPE)
if ($(PETSC_VERSION_PATCH) GREATER 0)
set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" CACHE INTERNAL "PETSc version")
else ()
set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}" CACHE INTERNAL "PETSc version")
endif ()
else ()
# make dev version compare higher than any patch level of a released version
set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" PARENT_SCOPE)
set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" CACHE INTERNAL "PETSc version")
endif ()
else ()
message (SEND_ERROR "PETSC_DIR can not be used, ${PETSC_DIR}/include/petscversion.h does not exist")
endif ()
endfunction ()
# Debian uses versioned paths e.g /usr/lib/petscdir/3.5/
file (GLOB DEB_PATHS "/usr/lib/petscdir/*")
find_path (PETSC_DIR include/petsc.h
HINTS ENV PETSC_DIR
PATHS
# Debian paths
/usr/lib/petsc
/usr/lib/petscdir/3.5.1 /usr/lib/petscdir/3.5
/usr/lib/petscdir/3.4.2 /usr/lib/petscdir/3.4
/usr/lib/petscdir/3.3 /usr/lib/petscdir/3.2 /usr/lib/petscdir/3.1
/usr/lib/petscdir/3.0.0 /usr/lib/petscdir/2.3.3 /usr/lib/petscdir/2.3.2
# Debian paths
${DEB_PATHS}
# Arch Linux path
/opt/petsc/linux-c-opt
# MacPorts path
/opt/local/lib/petsc
$ENV{HOME}/petsc
......@@ -198,7 +211,7 @@ show :
else (WIN32)
set (libname ${name})
endif (WIN32)
find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} ${libname}_real HINTS ${petsc_lib_dir} NO_DEFAULT_PATH)
find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH)
set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}")
mark_as_advanced (PETSC_LIBRARY_${suffix})
endmacro (PETSC_FIND_LIBRARY suffix name)
......@@ -244,11 +257,6 @@ show :
include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns)
macro (PETSC_TEST_RUNS includes libraries runs)
if(${PETSC_LANGUAGE_BINDINGS} STREQUAL "C")
set(_PETSC_ERR_FUNC "CHKERRQ(ierr)")
elseif(${PETSC_LANGUAGE_BINDINGS} STREQUAL "CXX")
set(_PETSC_ERR_FUNC "CHKERRXX(ierr)")
endif()
if (PETSC_VERSION VERSION_GREATER 3.1)
set (_PETSC_TSDestroy "TSDestroy(&ts)")
else ()
......@@ -262,15 +270,15 @@ int main(int argc,char *argv[]) {
PetscErrorCode ierr;
TS ts;
ierr = PetscInitialize(&argc,&argv,0,help);${_PETSC_ERR_FUNC};
ierr = TSCreate(PETSC_COMM_WORLD,&ts);${_PETSC_ERR_FUNC};
ierr = TSSetFromOptions(ts);${_PETSC_ERR_FUNC};
ierr = ${_PETSC_TSDestroy};${_PETSC_ERR_FUNC};
ierr = PetscFinalize();${_PETSC_ERR_FUNC};
ierr = PetscInitialize(&argc,&argv,0,help);CHKERRQ(ierr);
ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
ierr = ${_PETSC_TSDestroy};CHKERRQ(ierr);
ierr = PetscFinalize();CHKERRQ(ierr);
return 0;
}
")
multipass_source_runs ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}")
multipass_source_runs ("${includes};${MPI_CXX_INCLUDE_PATH}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}")
if (${${runs}})
set (PETSC_EXECUTABLE_RUNS "YES" CACHE BOOL
"Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." FORCE)
......@@ -333,5 +341,6 @@ endif ()
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (PETSc
"PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH."
PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS)
REQUIRED_VARS PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS
VERSION_VAR PETSC_VERSION
FAIL_MESSAGE "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH.")
# - Find python libraries
# This module finds the libraries corresponding to the Python interpeter
# FindPythonInterp provides.
# This code sets the following variables:
#
# PYTHONLIBS_FOUND - have the Python libs been found
# PYTHON_PREFIX - path to the Python installation
# PYTHON_LIBRARIES - path to the python library
# PYTHON_INCLUDE_DIRS - path to where Python.h is found
# PYTHON_SITE_PACKAGES - path to installation site-packages
# PYTHON_IS_DEBUG - whether the Python interpreter is a debug build
#
# PYTHON_INCLUDE_PATH - path to where Python.h is found (deprecated)
#
# A function PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is defined to build modules for python.
#=============================================================================
# Copyright 2001-2009 Kitware, Inc.
# Copyright 2012 Continuum Analytics, Inc.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the names of Kitware, Inc., the Insight Software Consortium,
# nor the names of their contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Use the Python interpreter to find the libs.
if(PythonLibsNew_FIND_REQUIRED)
find_package(PythonInterp REQUIRED)
else()
find_package(PythonInterp)
endif()
if(NOT PYTHONINTERP_FOUND)
set(PYTHONLIBS_FOUND FALSE)
return()
endif()
# According to http://stackoverflow.com/questions/646518/python-how-to-detect-debug-interpreter
# testing whether sys has the gettotalrefcount function is a reliable, cross-platform
# way to detect a CPython debug interpreter.
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
"from distutils import sysconfig as s;import sys;import struct;
print('.'.join(str(v) for v in sys.version_info));
print(s.PREFIX);
print(s.get_python_inc(plat_specific=True));
print(s.get_python_lib(plat_specific=True));
print(s.get_config_var('SO'));
print(hasattr(sys, 'gettotalrefcount')+0);
print(struct.calcsize('@P'));
"
RESULT_VARIABLE _PYTHON_SUCCESS
OUTPUT_VARIABLE _PYTHON_VALUES
ERROR_VARIABLE _PYTHON_ERROR_VALUE
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT _PYTHON_SUCCESS MATCHES 0)
if(PythonLibsNew_FIND_REQUIRED)
message(FATAL_ERROR
"Python config failure:\n${_PYTHON_ERROR_VALUE}")
endif()
set(PYTHONLIBS_FOUND FALSE)
return()
endif()
# Convert the process output into a list
string(REGEX REPLACE ";" "\\\\;" _PYTHON_VALUES ${_PYTHON_VALUES})
string(REGEX REPLACE "\n" ";" _PYTHON_VALUES ${_PYTHON_VALUES})
list(GET _PYTHON_VALUES 0 _PYTHON_VERSION_LIST)
list(GET _PYTHON_VALUES 1 PYTHON_PREFIX)
list(GET _PYTHON_VALUES 2 PYTHON_INCLUDE_DIR)
list(GET _PYTHON_VALUES 3 PYTHON_SITE_PACKAGES)
list(GET _PYTHON_VALUES 4 PYTHON_MODULE_EXTENSION)
list(GET _PYTHON_VALUES 5 PYTHON_IS_DEBUG)
list(GET _PYTHON_VALUES 6 PYTHON_SIZEOF_VOID_P)
# Make sure the Python has the same pointer-size as the chosen compiler
if(NOT ${PYTHON_SIZEOF_VOID_P} MATCHES ${CMAKE_SIZEOF_VOID_P})
if(PythonLibsNew_FIND_REQUIRED)
math(EXPR _PYTHON_BITS "${PYTHON_SIZEOF_VOID_P} * 8")
math(EXPR _CMAKE_BITS "${CMAKE_SIZEOF_VOID_P} * 8")
message(FATAL_ERROR
"Python config failure: Python is ${_PYTHON_BITS}-bit, "
"chosen compiler is ${_CMAKE_BITS}-bit")
endif()
set(PYTHONLIBS_FOUND FALSE)
return()
endif()
# The built-in FindPython didn't always give the version numbers
string(REGEX REPLACE "\\." ";" _PYTHON_VERSION_LIST ${_PYTHON_VERSION_LIST})
list(GET _PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
list(GET _PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
list(GET _PYTHON_VERSION_LIST 2 PYTHON_VERSION_PATCH)
# Make sure all directory separators are '/'
string(REGEX REPLACE "\\\\" "/" PYTHON_PREFIX ${PYTHON_PREFIX})
string(REGEX REPLACE "\\\\" "/" PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR})
string(REGEX REPLACE "\\\\" "/" PYTHON_SITE_PACKAGES ${PYTHON_SITE_PACKAGES})
# TODO: All the nuances of CPython debug builds have not been dealt with/tested.
if(PYTHON_IS_DEBUG)
set(PYTHON_MODULE_EXTENSION "_d${PYTHON_MODULE_EXTENSION}")
endif()
if(CMAKE_HOST_WIN32)
set(PYTHON_LIBRARY
"${PYTHON_PREFIX}/libs/Python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}.lib")
elseif(APPLE)
set(PYTHON_LIBRARY
"${PYTHON_PREFIX}/lib/libpython${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.dylib")
else()
if(${PYTHON_SIZEOF_VOID_P} MATCHES 8)
set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib64" "${PYTHON_PREFIX}/lib")
else()
set(_PYTHON_LIBS_SEARCH "${PYTHON_PREFIX}/lib")
endif()
# Probably this needs to be more involved. It would be nice if the config
# information the python interpreter itself gave us were more complete.
find_library(PYTHON_LIBRARY
NAMES
python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}
python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}mu
python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}m
python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}u
python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}
PATHS ${_PYTHON_LIBS_SEARCH}
NO_SYSTEM_ENVIRONMENT_PATH)
endif()
# For backward compatibility, set PYTHON_INCLUDE_PATH, but make it internal.
SET(PYTHON_INCLUDE_PATH "${PYTHON_INCLUDE_DIR}" CACHE INTERNAL
"Path to where Python.h is found (deprecated)")
# Added setting of PYTHONLIBS_VERSION_STRING from latest FindPythonLibs since
# this is required by ThirdPartyBoost
if(PYTHON_INCLUDE_DIR AND EXISTS "${PYTHON_INCLUDE_DIR}/patchlevel.h")
file(STRINGS "${PYTHON_INCLUDE_DIR}/patchlevel.h" python_version_str
REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
string(REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
PYTHONLIBS_VERSION_STRING "${python_version_str}")
unset(python_version_str)
endif()
MARK_AS_ADVANCED(
PYTHON_LIBRARY
PYTHON_INCLUDE_DIR
)
# We use PYTHON_INCLUDE_DIR, PYTHON_LIBRARY and PYTHON_DEBUG_LIBRARY for the
# cache entries because they are meant to specify the location of a single
# library. We now set the variables listed by the documentation for this
# module.
SET(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}")
SET(PYTHON_LIBRARIES "${PYTHON_LIBRARY}")
SET(PYTHON_DEBUG_LIBRARIES "${PYTHON_DEBUG_LIBRARY}")
# Don't know how to get to this directory, just doing something simple :P
#INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
#FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibs DEFAULT_MSG PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS)
find_package_message(PYTHON
"Found PythonLibs: ${PYTHON_LIBRARY}"
"${PYTHON_EXECUTABLE}${PYTHON_VERSION}")
# PYTHON_ADD_MODULE(<name> src1 src2 ... srcN) is used to build modules for python.
FUNCTION(PYTHON_ADD_MODULE _NAME )
GET_PROPERTY(_TARGET_SUPPORTS_SHARED_LIBS
GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
OPTION(PYTHON_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE)
OPTION(PYTHON_MODULE_${_NAME}_BUILD_SHARED
"Add module ${_NAME} shared" ${_TARGET_SUPPORTS_SHARED_LIBS})
# Mark these options as advanced
MARK_AS_ADVANCED(PYTHON_ENABLE_MODULE_${_NAME}
PYTHON_MODULE_${_NAME}_BUILD_SHARED)
IF(PYTHON_ENABLE_MODULE_${_NAME})
IF(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
SET(PY_MODULE_TYPE MODULE)
ELSE(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
SET(PY_MODULE_TYPE STATIC)
SET_PROPERTY(GLOBAL APPEND PROPERTY PY_STATIC_MODULES_LIST ${_NAME})
ENDIF(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
SET_PROPERTY(GLOBAL APPEND PROPERTY PY_MODULES_LIST ${_NAME})
ADD_LIBRARY(${_NAME} ${PY_MODULE_TYPE} ${ARGN})
TARGET_LINK_LIBRARIES(${_NAME} ${PYTHON_LIBRARIES})
IF(PYTHON_MODULE_${_NAME}_BUILD_SHARED)
SET_TARGET_PROPERTIES(${_NAME} PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}")
SET_TARGET_PROPERTIES(${_NAME} PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}")
ELSE()
ENDIF()
ENDIF(PYTHON_ENABLE_MODULE_${_NAME})
ENDFUNCTION(PYTHON_ADD_MODULE)
......@@ -249,3 +249,43 @@ MACRO(ADD_NEKTAR_TEST name)
COMMAND Tester ${CMAKE_CURRENT_SOURCE_DIR}/Tests/${name}.tst)
ENDIF()
ENDMACRO(ADD_NEKTAR_TEST)
#
# ADD_NEKPY_LIBRARY(name SOURCES src1 src2 ...)
#
# Adds a new NekPy library with the given sources.
#
MACRO(ADD_NEKPY_LIBRARY name)
CMAKE_PARSE_ARGUMENTS(NEKPY "" "" "SOURCES" ${ARGN})
SET(NEKPY_NAME ${name})
# Create library.
ADD_LIBRARY(_${name} SHARED ${NEKPY_SOURCES})
# Python requires a .so extension, even on OS X.
SET_TARGET_PROPERTIES(_${name} PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES(_${name} PROPERTIES SUFFIX ".so")
ADD_DEPENDENCIES(_${name} boost-numpy)
# Add target link libraries.
TARGET_LINK_LIBRARIES(_${name}
${Boost_SYSTEM_LIBRARY}
${BOOST_PYTHON_LIB}
${BOOST_NUMPY_LIB}
${PYTHON_LIBRARIES}
${name})
# Install __init__.py files.
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/python/init.py.in
${CMAKE_BINARY_DIR}/NekPy/${name}/__init__.py)
SET_TARGET_PROPERTIES(_${name} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/NekPy/${name})
ENDMACRO()
MACRO(ADD_NEKPY_EXECUTABLE name source)
# Copy the files into binary directory.
INSTALL(FILES ${source} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
FILE(COPY ${source} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
ADD_CUSTOM_TARGET(${name} SOURCES ${source})
ENDMACRO()
\ No newline at end of file
......@@ -8,12 +8,15 @@
#If the user has not set BOOST_ROOT, look in a couple common places first.
MESSAGE(STATUS "Searching for Boost:")
# Minimum version and boost libraries required
SET(MIN_VER "1.56.0")
SET(NEEDED_BOOST_LIBS thread iostreams filesystem system program_options regex)
SET(Boost_NO_BOOST_CMAKE ON)
IF( BOOST_ROOT )
SET(Boost_NO_SYSTEM_PATHS ON)
FIND_PACKAGE( Boost ${MIN_VER} COMPONENTS ${NEEDED_BOOST_LIBS})
FIND_PACKAGE( Boost ${MIN_VER} QUIET COMPONENTS ${NEEDED_BOOST_LIBS})
ELSE ()
SET(TEST_ENV1 $ENV{BOOST_HOME})
SET(TEST_ENV2 $ENV{BOOST_DIR})
......@@ -34,7 +37,7 @@ ENDIF()
# Check what we found and determine if we need to build boost
FOREACH(FOUND_VAR ${NEEDED_BOOST_LIBS})
STRING(TOUPPER ${FOUND_VAR} FOUND_VAR_UPPER)
IF (Boost_${FOUND_VAR_UPPER}_FOUND )
IF (Boost_${FOUND_VAR_UPPER}_FOUND)
MESSAGE(STATUS "-- Found Boost ${FOUND_VAR} library: "
"${Boost_${FOUND_VAR_UPPER}_LIBRARY}")
ELSE ()
......
########################################################################
#
# ThirdParty configuration for Nektar++
#
# Python interfaces
#
########################################################################
IF (NEKTAR_BUILD_PYTHON)
CMAKE_DEPENDENT_OPTION(NEKTAR_USE_PYTHON3
"If true, prefer to use Python 3." OFF "NEKTAR_BUILD_PYTHON" OFF)
# Unset any existing python executable/library settings so that
# we can rediscover correct python version if v2/3 settings changed
unset(PYTHON_EXECUTABLE CACHE)
unset(PYTHON_INCLUDE_DIR CACHE)
unset(PYTHON_LIBRARY CACHE)
unset(PYTHON_LIBRARY_DEBUG CACHE)
SET(PYTHONVER 2.7)
IF (NEKTAR_USE_PYTHON3)
SET(PYTHONVER 3.0)
ENDIF()
# Find Python
FIND_PACKAGE(PythonInterp ${PYTHONVER} REQUIRED)
FIND_PACKAGE(PythonLibsNew ${PYTHONVER} REQUIRED)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
ADD_DEFINITIONS(-DWITH_PYTHON)
# Include headers from root directory for config file.
# Now try to find Boost::Python. For now we are relying entirely on
# distributed versions of this (versus trying to compile via ThirdParty)
# because they come with various names and FindBoost is not really geared up
# for this at present. Therefore this is done separately to avoid lots of
# warnings and extraneous output.
#
# We need to try a few variants, depending on if we're doing Python 2 or
# Python 3. Irritatingly this is all very much distriution dependent so we
# just take our best guess at filenames. Seemingly from Boost 1.67 onwards,
# names are just `python27` and `numpy32` but for now we have to deal with
# this ourselves.
STRING(REPLACE "." ";" BOOST_PYTHON_VERSION ${PYTHONLIBS_VERSION_STRING})
LIST(GET BOOST_PYTHON_VERSION 0 BOOST_PYTHON_VERSION_MAJOR)
LIST(GET BOOST_PYTHON_VERSION 1 BOOST_PYTHON_VERSION_MINOR)
SET(TMP_BOOST_LIST ${NEEDED_BOOST_LIBS})
# If we're using multi-threaded, the existing library likely has a '-mt'
# suffix so we need to append this too.
IF (Boost_SYSTEM_LIBRARY MATCHES "-mt")
SET(BOOST_LIB_SUFFIX "-mt")
ENDIF()
# Try to find Boost::Python
FIND_LIBRARY(BOOST_PYTHON_LIB
NAMES boost_python-py${BOOST_PYTHON_VERSION_MAJOR}${BOOST_PYTHON_VERSION_MINOR}${BOOST_LIB_SUFFIX}
boost_python${BOOST_PYTHON_VERSION_MAJOR}${BOOST_PYTHON_VERSION_MINOR}${BOOST_LIB_SUFFIX}
boost_python-py${BOOST_PYTHON_VERSION_MAJOR}${BOOST_LIB_SUFFIX}
boost_python${BOOST_PYTHON_VERSION_MAJOR}${BOOST_LIB_SUFFIX}
boost_python${BOOST_LIB_SUFFIX}
PATHS ${Boost_LIBRARY_DIRS})
IF (NOT BOOST_PYTHON_LIB)
MESSAGE(FATAL_ERROR "Could not find Boost Python installation: check it is installed in your distribution.")
ENDIF()
MESSAGE(STATUS "Found Boost.Python: ${BOOST_PYTHON_LIB}")
# Try to find Boost.NumPy
FIND_LIBRARY(BOOST_NUMPY_LIB
NAMES boost_numpy-py${BOOST_PYTHON_VERSION_MAJOR}${BOOST_PYTHON_VERSION_MINOR}${BOOST_LIB_SUFFIX}
boost_numpy${BOOST_PYTHON_VERSION_MAJOR}${BOOST_PYTHON_VERSION_MINOR}${BOOST_LIB_SUFFIX}
boost_numpy-py${BOOST_PYTHON_VERSION_MAJOR}${BOOST_LIB_SUFFIX}
boost_numpy${BOOST_PYTHON_VERSION_MAJOR}${BOOST_LIB_SUFFIX}
boost_numpy${BOOST_LIB_SUFFIX}
PATHS ${Boost_LIBRARY_DIRS})
# If we can't find it, pull it from git and compile it
IF (NOT BOOST_NUMPY_LIB)
INCLUDE(ExternalProject)
EXTERNALPROJECT_ADD(
boost-numpy
PREFIX ${TPSRC}
URL ${TPURL}/boost-numpy_1.0.1.tar.bz2
URL_MD5 ae8c6f4d114a9c20dff72e915288a408
STAMP_DIR ${TPBUILD}/stamp
DOWNLOAD_DIR ${TPSRC}
SOURCE_DIR ${TPSRC}/boost-numpy
BINARY_DIR ${TPBUILD}/boost-numpy
TMP_DIR ${TPBUILD}/boost-numpy-tmp
INSTALL_DIR ${TPDIST}
CONFIGURE_COMMAND ${CMAKE_COMMAND}
-G ${CMAKE_GENERATOR} -DCMAKE_INSTALL_PREFIX:PATH=${TPDIST}
-DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
-DBUILD_EXAMPLES=OFF -DBUILD_TESTS=OFF -DLIBRARY_TYPE=STATIC
${TPSRC}/boost-numpy
)
IF (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
SET(BOOST_NUMPY_LIB ${TPDIST}/lib64/${CMAKE_STATIC_LIBRARY_PREFIX}boost_numpy${CMAKE_STATIC_LIBRARY_SUFFIX})
ELSE()
SET(BOOST_NUMPY_LIB ${TPDIST}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}boost_numpy${CMAKE_STATIC_LIBRARY_SUFFIX})
ENDIF()
INCLUDE_DIRECTORIES(SYSTEM ${TPDIST}/include)
MESSAGE(STATUS "Build Boost.NumPy: ${BOOST_NUMPY_LIB}")
ELSE()
MESSAGE(STATUS "Found Boost.NumPy: ${BOOST_NUMPY_LIB}")
ADD_CUSTOM_TARGET(boost-numpy ALL)
ADD_DEFINITIONS(-DBOOST_HAS_NUMPY)
ENDIF()
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/python/setup.py.in ${CMAKE_BINARY_DIR}/setup.py)
ADD_CUSTOM_TARGET(nekpy-install-user
DEPENDS _MultiRegions
COMMAND ${PYTHON_EXECUTABLE} setup.py install --user
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
ADD_CUSTOM_TARGET(nekpy-install-system
DEPENDS _MultiRegions
COMMAND ${PYTHON_EXECUTABLE} setup.py install
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/NekPy)
FILE(WRITE ${CMAKE_BINARY_DIR}/NekPy/__init__.py "# Adjust dlopen flags to avoid OpenMPI issues
try:
import DLFCN as dl
import sys
sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)
except ImportError:
pass")
MARK_AS_ADVANCED(BOOST_PYTHON_LIB)
MARK_AS_ADVANCED(BOOST_NUMPY_LIB)
ENDIF()
......@@ -74,8 +74,8 @@ IF (NEKTAR_USE_SCOTCH)
${SCOTCH_SRC}/Make.inc/${SCOTCH_MAKE}
${SCOTCH_SRC}/Makefile.inc
BUILD_COMMAND $(MAKE) -C ${SCOTCH_SRC}
"CFLAGS=${SCOTCH_CFLAGS}"
"LDFLAGS=${SCOTCH_LDFLAGS}"
"CFLAGS=-I${TPDIST}/include ${SCOTCH_CFLAGS}"
"LDFLAGS=-L${TPDIST}/lib ${SCOTCH_LDFLAGS}"
"CLIBFLAGS=-fPIC" scotch
INSTALL_COMMAND $(MAKE) -C ${SCOTCH_SRC}
prefix=${TPDIST} install
......
from ._${NEKPY_NAME} import *
from distutils.core import setup
libs = ['LibUtilities', 'StdRegions', 'SpatialDomains', 'LocalRegions', 'MultiRegions']
setup(name='NekPy',
version='${NEKTAR_VERSION}',
description='Python wrappers for Nektar++',
license='MIT',
author='David Moxey',
author_email='D.Moxey@exeter.ac.uk',
url='https://www.nektar.info/',
package_dir={ '': '${CMAKE_BINARY_DIR}' },
packages=[ 'NekPy' ] + [ 'NekPy.%s' % l for l in libs ],
package_data={ 'NekPy.%s' % l : ['_%s.so' % l] for l in libs }
)
# About
This repository contains the `NekPy` Python wrappers for the Nektar++
spectral/_hp_ element framework. **As a disclaimer, thhese wrappings are
_experimental_ and _incomplete_.** You should not rely on their current
structure and API remaining unchanged.
Currently, representative classes from the `LibUtilities`, `StdRegions`,
`SpatialDomains`, `LocalRegions` and `MultiRegions` libraries have been wrapped
in order to show the proof-of-concept.
# Features and functionality
`NekPy` uses the `Boost.Python` library to provide a set of high-quality,
hand-written Python bindings for selected functions and classes in Nektar++. A
typical snippet could look something like:
```python
from NekPy.LibUtilities import PointsKey, PointsType, BasisKey, BasisType
from NekPy.StdRegions import StdQuadExp
import numpy as np
numModes = 8
numPts = 9
ptsKey = PointsKey(numPts, PointsType.GaussLobattoLegendre)
basisKey = BasisKey(BasisType.Modified_A, numModes, ptsKey)
quadExp = StdQuadExp(basisKey, basisKey)
x, y = quadExp.GetCoords()
fx = np.sin(x) * np.cos(y)
proj = quadExp.FwdTrans(fx)
```
This example shows how to create a `StdQuadExp` and perform a rudimentary
forwards transform using the `NekPy` wrappers.
`NekPy` additionally uses the `Boost.NumPy` library, contained in Boost 1.63+,
to automatically convert C++ `Array<OneD, T>` objects to and from the
commonly-used `numpy.ndarray` object, which makes the integration more seamless
between Python and C++.
# How do I wrap things?
`Boost.Python` is a pretty comprehensive package and an extended discussion is
really beyond the scope of this project. See [the wrapping
guide](wrapping-guide.md) for some basic concepts and frequently-encountered
issues.
# Compiling
NekPy has the following list of requirements:
- Boost with Python support
- Python 2.7+
- NumPy, installed either from your package manager or through `pip`.
Most of these can be installed using package managers on various operating
systems, as we describe below. We also have a requirement on the `Boost.NumPy`
package, which is available in boost 1.63 or later. If this isn't found on your
system, it will be automatically downloaded and compiled.
## Compiling and installing Nektar++ with NekPy support
Nektar++ should be compiled as per the user guide instructions. To build the
`NekPy` wrapper, you should ensure that the `NEKTAR_BUILD_PYTHON` option is
enabled.
### macOS
#### Homebrew
Users of Homebrew should make sure their installation is up-to-date with `brew
upgrade`. Then run
```
brew install python boost-python
```
To install the NumPy package, use the `pip` package manager:
```
pip install numpy
```
#### MacPorts
Users of MacPorts should sure their installation is up-to-date with `sudo port
selfupdate && sudo port upgrade outdated`. Then run
```
sudo port install python27 py27-numpy
sudo port select --set python python27
```
### Linux: Ubuntu/Debian
Users of Debian and Ubuntu Linux systems should sure their installation is
up-to-date with `sudo apt-get update && sudo apt-get upgrade`
```
sudo apt-get install libboost-python-dev python-numpy
```
## Installing the wrappers
Run the following command in `$NEKDIR/build` directory to install the Python package
for the current user:
```