Commit 821dc089 authored by Spencer Sherwin's avatar Spencer Sherwin

First attempt to merge old python files to this branch

parent 0e65b3b8
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
# Nektar++ requires C++11. Try to infer this for older CMake versions (less than
# 3.1.0)
IF ("${CMAKE_VERSION}" VERSION_LESS "3.1")
IF (NOT MSVC)
INCLUDE(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
IF (COMPILER_SUPPORTS_CXX11)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ELSE()
MESSAGE(FATAL_ERROR "Nektar++ requires a compiler with C++11 support.")
ENDIF()
ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
MESSAGE(FATAL_ERROR "Nektar++ requires full C++11 support: please upgrade to Visual Studio 2013 or later")
ENDIF()
ELSE()
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)
ENDIF()
# Default install location
IF (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/dist CACHE PATH "" FORCE)
ENDIF()
# Find Nektar++
FIND_PACKAGE(Nektar++ REQUIRED)
ADD_DEFINITIONS(${NEKTAR++_DEFINITIONS})
INCLUDE_DIRECTORIES(SYSTEM ${NEKTAR++_INCLUDE_DIRS} ${NEKTAR++_TP_INCLUDE_DIRS})
LINK_DIRECTORIES(${NEKTAR++_LIBRARY_DIRS} ${NEKTAR++_TP_LIBRARY_DIRS})
MESSAGE(STATUS "Found Nektar++: version ${NEKTAR++_VERSION}")
# Set up RPATH so that we grab Nektar++ libraries
SET(CMAKE_MACOSX_RPATH ON)
SET(CMAKE_INSTALL_RPATH ${NEKTAR++_LIBRARY_DIRS})
# Find Boost.Python
FIND_PACKAGE(Boost REQUIRED COMPONENTS python system)
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS})
SET(BOOST_TMP_LIBS "${Boost_LIBRARIES}")
# Find Python
FIND_PACKAGE(PythonInterp REQUIRED)
FIND_PACKAGE(PythonLibsNew REQUIRED)
INCLUDE_DIRECTORIES(SYSTEM ${PYTHON_INCLUDE_DIRS})
# Fix RPATH issue on OS X
SET(TPSRC ${CMAKE_SOURCE_DIR}/ThirdParty)
SET(TPBUILD ${CMAKE_BINARY_DIR}/ThirdParty)
SET(TPDIST ${CMAKE_BINARY_DIR}/ThirdParty/dist)
IF (NOT EXISTS ${TPSRC})
FILE(MAKE_DIRECTORY ${TPSRC})
ENDIF ()
# Include headers from root directory for config file.
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
# Try to find Boost.NumPy
FIND_LIBRARY(BOOST_NUMPY_LIB boost_numpy 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}
GIT_REPOSITORY http://github.com/ndarray/Boost.NumPy.git
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}
${TPSRC}/boost-numpy
)
message(STATUS ${TPDIST})
SET(BOOST_NUMPY_LIB ${TPDIST}/lib64/${CMAKE_SHARED_LIBRARY_PREFIX}boost_numpy${CMAKE_SHARED_LIBRARY_SUFFIX})
INCLUDE_DIRECTORIES(SYSTEM ${TPDIST}/include)
# Add this directory to the RPATH.
SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH} ${TPDIST}/lib64)
ELSE()
ADD_CUSTOM_TARGET(boost-numpy ALL)
ADD_DEFINITIONS(-DBOOST_HAS_NUMPY)
ENDIF()
# Define a macro which will create our libraries.
MACRO(ADD_NEKPY_LIBRARY name sources)
ADD_LIBRARY(_${name} SHARED ${${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_TMP_LIBS}
${BOOST_NUMPY_LIB}
${PYTHON_LIBRARIES}
${NEKTAR++_LIBRARIES}
${NEKTAR++_TP_LIBRARIES}
)
INSTALL(TARGETS _${name} DESTINATION
${CMAKE_INSTALL_PREFIX}/NekPy/${name})
ENDMACRO()
# Add libraries.
ADD_SUBDIRECTORY(LibUtilities)
ADD_SUBDIRECTORY(StdRegions)
ADD_SUBDIRECTORY(SpatialDomains)
ADD_SUBDIRECTORY(LocalRegions)
ADD_SUBDIRECTORY(MultiRegions)
# Copy lib structure.
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/lib/
DESTINATION ${CMAKE_INSTALL_PREFIX}/NekPy)
# Copy examples
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/example/
DESTINATION ${CMAKE_INSTALL_PREFIX})
#include <LibUtilities/BasicUtils/SessionReader.h>
#include <NekPyConfig.hpp>
using namespace Nektar::LibUtilities;
/**
* @brief Thin wrapper around SessionReader to provide a nicer Pythonic
* interface.
*
* This allows us to do, for example
*
* session = SessionReader.CreateInstance(sys.argv)
*
* which is more natural in Python.
*/
SessionReaderSharedPtr SessionReader_CreateInstance(py::list &ns)
{
int i, argc = py::len(ns), bufSize = 0;
char **argv = new char *[argc+1], *p;
// Create argc, argv to give to the session reader. Note that this needs to
// be a contiguous block in memory, otherwise MPI (specifically OpenMPI)
// will likely segfault.
for (i = 0; i < argc; ++i)
{
std::string tmp = py::extract<std::string>(ns[i]);
bufSize += tmp.size() + 1;
}
std::vector<char> buf(bufSize);
for (i = 0, p = &buf[0]; i < argc; ++i)
{
std::string tmp = py::extract<std::string>(ns[i]);
std::copy(tmp.begin(), tmp.end(), p);
p[tmp.size()] = '\0';
argv[i] = p;
p += tmp.size()+1;
}
// Also make sure we set argv[argc] = NULL otherwise OpenMPI will also
// segfault.
argv[argc] = NULL;
// Create session reader.
SessionReaderSharedPtr sr = SessionReader::CreateInstance(argc, argv);
// Clean up.
delete [] argv;
return sr;
}
/**
* @brief SessionReader exports.
*
* Currently wrapped functions:
* - SessionReader::CreateInstance for creating objects
* - SessionReader::GetSessionName to return the session name
* - SessionReader::Finalise to deal with finalising things
*/
void export_SessionReader()
{
py::class_<SessionReader,
std::shared_ptr<SessionReader>,
boost::noncopyable>(
"SessionReader", py::no_init)
.def("CreateInstance", SessionReader_CreateInstance)
.staticmethod("CreateInstance")
.def("GetSessionName", &SessionReader::GetSessionName,
py::return_value_policy<py::copy_const_reference>())
.def("Finalise", &SessionReader::Finalise)
;
}
#include <vector>
#include <LibUtilities/BasicUtils/ShapeType.hpp>
#include <NekPyConfig.hpp>
using namespace Nektar::LibUtilities;
/**
* @brief Export for ShapeType enumeration.
*/
void export_ShapeType()
{
py::enum_<ShapeType> tmp("ShapeType");
for (int i = 0; i < (int)SIZE_ShapeType; ++i)
{
tmp.value(ShapeTypeMap[i], (ShapeType) i);
}
tmp.export_values();
}
#include <LibUtilities/BasicUtils/SharedArray.hpp>
#include <NekPyConfig.hpp>
using namespace Nektar;
using namespace Nektar::LibUtilities;
#if PY_MAJOR_VERSION == 2
template<typename T>
void CapsuleDestructor(void *ptr)
{
Array<OneD, T> *tmp = (Array<OneD, T> *)ptr;
delete tmp;
}
#else
template<typename T>
void CapsuleDestructor(PyObject *ptr)
{
Array<OneD, T> *tmp = (Array<OneD, T> *)PyCapsule_GetPointer(ptr, 0);
delete tmp;
}
#endif
template<typename T>
struct OneDArrayToPython
{
static PyObject *convert(Array<OneD, T> const &arr)
{
// Create a Python capsule to hold a pointer that contains a lightweight
// copy of arr. That way we guarantee Python will still have access to
// the memory allocated inside arr even if arr is deallocated in C++.
#if PY_MAJOR_VERSION == 2
py::object capsule(
py::handle<>(PyCObject_FromVoidPtr(
new Array<OneD, T>(arr), CapsuleDestructor<T>)));
#else
py::object capsule(
py::handle<>(PyCapsule_New(
new Array<OneD, T>(arr), 0,
(PyCapsule_Destructor)&CapsuleDestructor<T>)));
#endif
return py::incref(
np::from_data(
arr.data(), np::dtype::get_builtin<T>(),
py::make_tuple(arr.num_elements()), py::make_tuple(sizeof(T)),
capsule).ptr());
}
};
template <typename T>
struct PythonToOneDArray
{
PythonToOneDArray()
{
py::converter::registry::push_back(
&convertible, &construct, py::type_id<Array<OneD, T> >());
}
static void *convertible(PyObject *objPtr)
{
try
{
py::object obj((py::handle<>(py::borrowed(objPtr))));
np::ndarray array = py::extract<np::ndarray>(obj);
// Check data types match
np::dtype dtype = np::dtype::get_builtin<
typename boost::remove_const<T>::type>();
if (dtype != array.get_dtype())
{
return 0;
}
// Check shape is 1D
if (array.get_nd() != 1)
{
return 0;
}
}
catch (boost::python::error_already_set)
{
py::handle_exception();
PyErr_Clear();
return 0;
}
return objPtr;
}
static void construct(
PyObject *objPtr,
py::converter::rvalue_from_python_stage1_data* data)
{
// This has to be a _borrowed_ reference, otherwise at the end of this
// scope it seems memory gets deallocated
py::object obj((py::handle<>(py::borrowed(objPtr))));
np::ndarray array = py::extract<np::ndarray>(obj);
// Construct OneD array from numpy array
void *storage = (
(py::converter::rvalue_from_python_storage<Array<OneD, T> >*)data)
->storage.bytes;
data->convertible = storage;
new (storage) Array<OneD, T>(array.shape(0), (T *)array.get_data());
}
};
template<typename T>
void export_SharedArray()
{
py::to_python_converter<Array<OneD, const T>, OneDArrayToPython<const T> >();
py::to_python_converter<Array<OneD, T>, OneDArrayToPython<T> >();
PythonToOneDArray<const T>();
PythonToOneDArray<T>();
}
template void export_SharedArray<double>();
SET(LIBUTILITIES_SOURCES
LibUtilities.cpp
BasicUtils/SessionReader.cpp
BasicUtils/SharedArray.cpp
BasicUtils/ShapeType.cpp
Foundations/Basis.cpp
Foundations/Points.cpp
)
ADD_NEKPY_LIBRARY(LibUtilities LIBUTILITIES_SOURCES)
#include <LibUtilities/Foundations/Basis.h>
#include <LibUtilities/Foundations/ManagerAccess.h>
#include <NekPyConfig.hpp>
using namespace Nektar::LibUtilities;
BasisSharedPtr Basis_Create(const BasisKey &pts)
{
return BasisManager()[pts];
}
py::tuple Basis_GetZW(BasisSharedPtr pts)
{
return py::make_tuple(pts->GetZ(), pts->GetW());
}
/**
* @brief Basis exports.
*/
void export_Basis()
{
// Enumerator for basis type
NEKPY_WRAP_ENUM(BasisType, BasisTypeMap);
py::class_<BasisKey>("BasisKey", py::init<const BasisType&, const int,
const PointsKey&>())
.def("GetNumModes", &BasisKey::GetNumModes)
.def("GetTotNumModes", &BasisKey::GetTotNumModes)
.def("GetNumPoints", &BasisKey::GetNumPoints)
.def("GetTotNumPoints", &BasisKey::GetTotNumPoints)
.def("GetBasisType", &BasisKey::GetBasisType)
.def("GetPointsKey", &BasisKey::GetPointsKey)
.def("GetPointsType", &BasisKey::GetPointsType)
.def("Collocation", &BasisKey::Collocation)
;
py::class_<Basis,
std::shared_ptr<Basis> >(
"Basis", py::no_init)
.def("Create", &Basis_Create)
.staticmethod("Create")
.def("GetNumModes", &Basis::GetNumModes)
.def("GetTotNumModes", &Basis::GetTotNumModes)
.def("GetNumPoints", &Basis::GetNumPoints)
.def("GetTotNumPoints", &Basis::GetTotNumPoints)
.def("GetBasisType", &Basis::GetBasisType)
.def("GetPointsKey", &Basis::GetPointsKey)
.def("GetBasisKey", &Basis::GetBasisKey)
.def("GetPointsType", &Basis::GetBasisType)
.def("Initialize", &Basis::Initialize)
.def("GetZ", &Basis::GetZ,
py::return_value_policy<py::copy_const_reference>())
.def("GetW", &Basis::GetZ,
py::return_value_policy<py::copy_const_reference>())
.def("GetZW", &Basis_GetZW)
.def("GetBdata", &Basis::GetBdata,
py::return_value_policy<py::copy_const_reference>())
.def("GetDbdata", &Basis::GetDbdata,
py::return_value_policy<py::copy_const_reference>())
;
}
#include <LibUtilities/Foundations/ManagerAccess.h>
#include <LibUtilities/Foundations/Points.h>
#include <LibUtilities/Foundations/PointsType.h>
#include <NekPyConfig.hpp>
using namespace Nektar::LibUtilities;
typedef std::shared_ptr<Points<double> > PointsSharedPtr;
PointsSharedPtr Points_Create(const PointsKey &pts)
{
return PointsManager()[pts];
}
py::tuple Points_GetZW(PointsSharedPtr pts)
{
return py::make_tuple(pts->GetZ(), pts->GetW());
}
/**
* @brief Points exports.
*/
void export_Points()
{
NEKPY_WRAP_ENUM_STRING(PointsType, kPointsTypeStr);
py::class_<PointsKey>("PointsKey", py::init<const int, const PointsType&>())
.def("GetNumPoints", &PointsKey::GetNumPoints)
.def("GetPointsType", &PointsKey::GetPointsType)
.def("GetPointsDim", &PointsKey::GetPointsDim)
.def("GetTotNumPoints", &PointsKey::GetTotNumPoints)
;
py::class_<Points<double>,
std::shared_ptr<Points<double> >,
boost::noncopyable>(
"Points", py::no_init)
.def("Create", &Points_Create)
.staticmethod("Create")
.def("Initialise", &Points<double>::Initialize)
.def("GetPointsDim", &Points<double>::GetPointsDim)
.def("GetPointsType", &Points<double>::GetPointsType)
.def("GetNumPoints", &Points<double>::GetNumPoints)
.def("GetTotNumPoints", &Points<double>::GetTotNumPoints)
.def("GetZ", &Points<double>::GetZ,
py::return_value_policy<py::copy_const_reference>())
.def("GetW", &Points<double>::GetZ,
py::return_value_policy<py::copy_const_reference>())
.def("GetZW", &Points_GetZW)
;
}
#include <NekPyConfig.hpp>
void export_Basis();
void export_Points();
void export_SessionReader();
void export_ShapeType();
template<typename T>
void export_SharedArray();
BOOST_PYTHON_MODULE(_LibUtilities)
{
np::initialize();
export_Basis();
export_Points();
export_SessionReader();
export_ShapeType();
export_SharedArray<double>();
}
SET(LOCALREGIONS_SOURCES
LocalRegions.cpp
Expansion.cpp
QuadExp.cpp
SegExp.cpp
TriExp.cpp
)
ADD_NEKPY_LIBRARY(LocalRegions LOCALREGIONS_SOURCES)
#include <NekPyConfig.hpp>
#include <LocalRegions/Expansion.h>
using namespace Nektar;
using namespace Nektar::StdRegions;
using namespace Nektar::LocalRegions;
using namespace Nektar::SpatialDomains;
void export_Expansion()
{
py::class_<Expansion,
std::shared_ptr<Expansion>, py::bases<StdExpansion>,
boost::noncopyable>(
"Expansion", py::no_init)
.def("GetGeom", &Expansion::GetGeom)
;
}
#include <NekPyConfig.hpp>
void export_Expansion();
void export_SegExp();
void export_TriExp();
void export_QuadExp();
BOOST_PYTHON_MODULE(_LocalRegions)
{
np::initialize();
export_Expansion();
export_SegExp();
export_TriExp();
export_QuadExp();
}
#include <NekPyConfig.hpp>
#include <LocalRegions/QuadExp.h>
using namespace Nektar;
using namespace Nektar::LocalRegions;
void export_QuadExp()
{
py::class_<QuadExp, py::bases<Expansion, StdRegions::StdQuadExp>,
std::shared_ptr<QuadExp> >(
"QuadExp", py::init<const LibUtilities::BasisKey&,
const LibUtilities::BasisKey&,
const SpatialDomains::QuadGeomSharedPtr &>());
}
#include <NekPyConfig.hpp>
#include <LocalRegions/SegExp.h>
using namespace Nektar;
using namespace Nektar::LocalRegions;
void export_SegExp()
{
py::class_<SegExp, py::bases<Expansion, StdRegions::StdSegExp>,
std::shared_ptr<SegExp> >(
"SegExp", py::init<const LibUtilities::BasisKey&,
const SpatialDomains::Geometry1DSharedPtr &>());
}
#include <NekPyConfig.hpp>
#include <LocalRegions/TriExp.h>
using namespace Nektar;
using namespace Nektar::LocalRegions;
void export_TriExp()
{
py::class_<TriExp, py::bases<Expansion, StdRegions::StdTriExp>,
std::shared_ptr<TriExp> >(
"TriExp", py::init<const LibUtilities::BasisKey&,
const LibUtilities::BasisKey&,
const SpatialDomains::TriGeomSharedPtr &>());
}
SET(MULTIREGIONS_SOURCES
MultiRegions.cpp
ExpList.cpp
ExpList2D.cpp
)
ADD_NEKPY_LIBRARY(MultiRegions MULTIREGIONS_SOURCES)
#include <NekPyConfig.hpp>
#include <MultiRegions/ExpList.h>
#include <fstream>