Skip to content
Open
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
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.19)
project(pcms VERSION 0.0.5 LANGUAGES CXX)
#set(CMAKE_CXX_VISIBILITY_PRESET "default")

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
Expand All @@ -16,11 +17,16 @@ option(PCMS_ENABLE_CLIENT "enable the coupling client implementation" ON)
option(PCMS_ENABLE_XGC "enable xgc field adapter" ON)
option(PCMS_ENABLE_OMEGA_H "enable Omega_h field adapter" OFF)
option(PCMS_ENABLE_C "Enable pcms C api" ON)
option(PCMS_ENABLE_Python "Enable pcms Python api" OFF)

# find package before fortran enabled, so we don't require the adios2 fortran interfaces
# this is important because adios2 build with clang/gfortran is broken
find_package(redev 4.3.0 REQUIRED)

if (PCMS_ENABLE_Python)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
endif ()
if (PCMS_ENABLE_C)
enable_language(C)
option(PCMS_ENABLE_Fortran "Enable pcms fortran api" ON)
Expand Down
8 changes: 8 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# TODO split out the field transfer library

set(PCMS_HEADERS
pcms.h
pcms/arrays.h
Expand Down Expand Up @@ -44,6 +45,7 @@ endif ()

find_package(Kokkos REQUIRED)
find_package(perfstubs REQUIRED)
find_package(pybind11 REQUIRED)

add_library(pcms_core ${PCMS_SOURCES})
set_target_properties(pcms_core PROPERTIES
Expand Down Expand Up @@ -116,6 +118,12 @@ if(PCMS_ENABLE_Fortran)
add_subdirectory(pcms/fortranapi)
target_link_libraries(pcms_pcms INTERFACE pcms::fortranapi)
endif()
if (PCMS_ENABLE_Python)
add_subdirectory(pcms/pythonapi)
#target_link_libraries(pcms_pcms INTERFACE pcms::pythonapi)
endif()

#add_subdirectory(pcms/pythonapi)

install(
TARGETS pcms_pcms
Expand Down
30 changes: 2 additions & 28 deletions src/pcms/capi/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,7 @@
#include <fstream>
#include "pcms/xgc_reverse_classification.h"
#include "pcms/dummy_field_adapter.h"
namespace pcms
{
// Note that we have a closed set of types that can be used in the C interface
using FieldAdapterVariant =
std::variant<std::monostate, pcms::XGCFieldAdapter<double>,
pcms::XGCFieldAdapter<float>, pcms::XGCFieldAdapter<int>,
pcms::XGCFieldAdapter<long>,
pcms::DummyFieldAdapter
//#ifdef PCMS_HAS_OMEGA_H
// ,
// pcms::OmegaHFieldAdapter<double>,
// pcms::OmegaHFieldAdapter<int>
//#endif
>;

} // namespace pcms
#include "client_cpp.h"

[[nodiscard]] PcmsClientHandle pcms_create_client(const char* name,
MPI_Comm comm)
Expand Down Expand Up @@ -116,18 +101,7 @@ void pcms_receive_field(PcmsFieldHandle field_handle)
PCMS_ALWAYS_ASSERT(field != nullptr);
field->Receive();
}
template <typename T>
void pcms_create_xgc_field_adapter_t(
const char* name, MPI_Comm comm, void* data, int size,
const pcms::ReverseClassificationVertex& reverse_classification,
in_overlap_function in_overlap, pcms::FieldAdapterVariant& field_adapter)
{
PCMS_ALWAYS_ASSERT((size >0) ? (data!=nullptr) : true);
pcms::ScalarArrayView<T, pcms::HostMemorySpace> data_view(
reinterpret_cast<T*>(data), size);
field_adapter.emplace<pcms::XGCFieldAdapter<T>>(
name, comm, data_view, reverse_classification, in_overlap);
}

PcmsFieldAdapterHandle pcms_create_xgc_field_adapter(
const char* name, MPI_Comm comm, void* data, int size, PcmsType data_type,
const PcmsReverseClassificationHandle rc, in_overlap_function in_overlap)
Expand Down
38 changes: 38 additions & 0 deletions src/pcms/capi/client_cpp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef PCMS_CLIENT_CPP_H
#define PCMS_CLIENT_CPP_H

#include <variant>

namespace pcms
{
//namespace detail {
// Note that we have a closed set of types that can be used in the C interface
using FieldAdapterVariant =
std::variant<std::monostate, pcms::XGCFieldAdapter<double>,
pcms::XGCFieldAdapter<float>, pcms::XGCFieldAdapter<int>,
pcms::XGCFieldAdapter<long>,
pcms::DummyFieldAdapter
//#ifdef PCMS_HAS_OMEGA_H
// ,
// pcms::OmegaHFieldAdapter<double>,
// pcms::OmegaHFieldAdapter<int>
//#endif
>;
//}

} // namespace pcms

template <typename T>
void pcms_create_xgc_field_adapter_t(
const char* name, MPI_Comm comm, void* data, int size,
const pcms::ReverseClassificationVertex& reverse_classification,
in_overlap_function in_overlap, pcms::FieldAdapterVariant& field_adapter)
{
PCMS_ALWAYS_ASSERT((size >0) ? (data!=nullptr) : true);
pcms::ScalarArrayView<T, pcms::HostMemorySpace> data_view(
reinterpret_cast<T*>(data), size);
field_adapter.emplace<pcms::XGCFieldAdapter<T>>(
name, comm, data_view, reverse_classification, in_overlap);
}

#endif
2 changes: 1 addition & 1 deletion src/pcms/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,4 @@ class CouplerClient
};
} // namespace pcms

#endif // PCMS_COUPLING_CLIENT_H
#endif // PCMS_COUPLING_CLIENT_H
75 changes: 75 additions & 0 deletions src/pcms/pythonapi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
find_package(Python REQUIRED)
include(FindPythonModule.cmake)
message(STATUS "Python_EXECUTABLE ${Python_EXECUTABLE}")
find_python_module(mpi4py REQUIRED)

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}")
endif()

pybind11_add_module(c_pcms_python c_client_pybind.cpp ../capi/kokkos.cpp ../capi/client.cpp)
pybind11_add_module(pcms_python client_pybind.cpp ../capi/kokkos.cpp)

target_include_directories(c_pcms_python
SYSTEM PRIVATE
${mpi4py_INCLUDE_DIRS}
)

target_include_directories(pcms_python
SYSTEM PRIVATE
${mpi4py_INCLUDE_DIRS}
)

set_target_properties(c_pcms_python pcms_python PROPERTIES CXX_STANDARD 17)
target_link_libraries(pcms_python PRIVATE Kokkos::kokkos pybind11::module MPI::MPI_C pcms::core)
target_link_libraries(c_pcms_python PRIVATE Kokkos::kokkos pybind11::module MPI::MPI_C pcms::core)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/PythonFieldAdapters.py ${CMAKE_CURRENT_SOURCE_DIR}/c_test_proxy_coupling_xgc_client.py
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})


install(
TARGETS c_pcms_python pcms_python
EXPORT pcms_python-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/pythonapi/)
install(
EXPORT pcms_python-targets
NAMESPACE pcms::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms)




92 changes: 92 additions & 0 deletions src/pcms/pythonapi/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()
Loading