Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Created a new bindings module for fortran and python that allows a dr…
Browse files Browse the repository at this point in the history
…iver program to be run directly from the Python side without using subprocess. Next step will be to fix the Simulation class so that it uses it
  • Loading branch information
MintoDA1 authored and MintoDA1 committed Aug 7, 2023
1 parent 10b098c commit 3957b4b
Show file tree
Hide file tree
Showing 21 changed files with 130 additions and 121 deletions.
37 changes: 2 additions & 35 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,57 +59,24 @@ INCLUDE_DIRECTORIES($ENV{NETCDF_FORTRAN_HOME}/include;$ENV{NETCDF_HOME}/include)
############################################################



# Define some directories
SET(SRC ${CMAKE_SOURCE_DIR}/src)
SET(LIB ${CMAKE_SOURCE_DIR}/lib)
SET(BIN ${CMAKE_SOURCE_DIR}/bin)
SET(MOD ${CMAKE_SOURCE_DIR}/include)
#SET(TEST ${CMAKE_SOURCE_DIR}/test)
SET(PY ${CMAKE_SOURCE_DIR}/src/python)
SET(PY ${CMAKE_SOURCE_DIR}/python)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN})


FUNCTION(REPLACE_VERSION IN_FILE LANGUAGE)
# Make list of strings from file
FILE(STRINGS ${IN_FILE} LINES)

# Replace file with new one
FILE(WRITE ${IN_FILE} "")

# Look for the word "VERSION" and replace the line with the updated one
FOREACH(LINE IN LISTS LINES)
IF (LANGUAGE STREQUAL "Fortran") # This is the version found in the swiftest driver program
STRING(FIND "${LINE}" " VERSION =" LINE_HAS_VER)
IF (LINE_HAS_VER GREATER_EQUAL 0) # This is the version line
FILE(APPEND ${IN_FILE} " character(*), parameter :: VERSION = \"${CMAKE_PROJECT_VERSION}\" !! Swiftest version\n")
ELSE ()
FILE(APPEND ${IN_FILE} "${LINE}\n") # No match. Put this line back like we found it
ENDIF ()
ELSEIF (LANGUAGE STREQUAL "Python") # This is the version found in the Python package
STRING(FIND "${LINE}" "version=" LINE_HAS_VER)
IF (LINE_HAS_VER GREATER_EQUAL 0) # This is the version line
FILE(APPEND ${IN_FILE} " version='${CMAKE_PROJECT_VERSION}',\n")
ELSE () # No match. Put this line back like we found it
STRING(REPLACE ";" "\n" LINE "${LINE}") # Fixes an issue when parsing the list that defines the pydriver extension module
FILE(APPEND ${IN_FILE} "${LINE}\n")
ENDIF ()
ENDIF ()
ENDFOREACH ()
ENDFUNCTION ()

REPLACE_VERSION(${SRC}/globals/globals_module.f90 "Fortran" )
REPLACE_VERSION(${PY}/setup.py "Python")


# Have the .mod files placed in the lib folder
SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD})

# The source for the SWIFTEST binary and have it placed in the bin folder
ADD_SUBDIRECTORY(${SRC} ${BIN})
ADD_SUBDIRECTORY(${PY})

# # Set up test directory
# ENABLE_TESTING()
Expand Down
12 changes: 5 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,9 @@ RUN wget https://repo.anaconda.com/miniconda/Miniconda3-py311_23.5.2-0-Linux-x86
-DBUILD_SHARED_LIBS=OFF \
${EXTRA_CMAKE_OPTIONS} && \
cmake --build build && \
cmake --install build && \
mv bin/CMakeFiles/swiftest.dir/__/python/swiftest/f2py/driver.f90.o python/swiftest/f2py/ && \
mv bin/CMakeFiles/swiftest.dir/__/python/swiftest/f2py/pydriver.f90.o python/swiftest/f2py/
cmake --install build

RUN cd swiftest/python/swiftest/f2py && \
RUN cd swiftest/python && \
python setup.py build_ext --inplace


Expand Down Expand Up @@ -167,17 +165,17 @@ ENV LD_LIBRARY_PATH="/usr/local/lib"
COPY --from=build_driver /usr/local/bin/swiftest_driver /opt/conda/bin/swiftest_driver
COPY --from=build_driver /usr/local/lib/libswiftest.a /opt/conda/lib/libswiftest.a
COPY --from=build_driver /swiftest/include/ /opt/conda/include/swiftest/
COPY ./python/. /opt/conda/pkgs/
COPY ./python/. /opt/conda/pkgs/swiftest/
COPY environment.yml .

RUN conda update --all -y && \
conda install conda-libmamba-solver -y && \
conda config --set solver libmamba && \
conda install conda-build -y && \
conda env create -f environment.yml && \
cd /opt/conda/pkgs/swiftest && conda develop . --name swiftest-env && \
conda init bash && \
echo "conda activate swiftest-env" >> ~/.bashrc && \
conda install -c anaconda cython -y && \
cd /opt/conda/pkgs/swiftest && pip install -e . && \
conda clean --all -y && \
mkdir -p /.astropy && \
chmod -R 777 /.astropy && \
Expand Down
1 change: 1 addition & 0 deletions distclean.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ FILE(GLOB_RECURSE MAKEFILE "${TOPDIR}/*Makefile")
FILE(GLOB_RECURSE CMAKETESTFILES "${TOPDIR}/*CTestTestfile.cmake")
SET(TOPDIRECTORIES "${TOPDIR}/lib"
"${TOPDIR}/bin"
"${TOPDIR}/include"
)

# CMake has trouble finding directories recursively, so locate these
Expand Down
10 changes: 10 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FIND_PACKAGE(Python COMPONENTS Interpreter REQUIRED)
IF(NOT ${PYTHON})
find_program(PYTHON "python")
ENDIF()

# Communicate version number and other CMake build variables to the source code
SET(SETUP_PY_IN "${PY}/setup.py.in")
SET(SETUP_PY_OUT "${PY}/setup.py")

CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY_OUT})
26 changes: 15 additions & 11 deletions src/python/setup.py → python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,26 @@
from Cython.Build import cythonize
import os

# Build the pydriver extension that allows us to run the Fortran driver as a Python module.
root_dir = 'pydriver'
include_dir = os.path.join(root_dir,'include')
lib_dir = os.path.join(root_dir,'lib')
pydriver_extension = [Extension('swiftest.pydriver',
[os.path.join(root_dir,'pydriver.pyx')],
extra_compile_args=['-fPIC', '-O3'],
library_dirs=[lib_dir],
libraries=['swiftest','netcdff','netcdf','hdf5_hl','hdf5','m','z'],
include_dirs=[include_dir],
# Build the pybindings extension that allows us to run the Fortran driver as a Python module.
root_dir = 'pybindings'
include_dirs = "/Users/daminton/git/swiftest/apple_install/usr/local/include;/Users/daminton/git/swiftest/apple_install/usr/local/include"
include_dirs = include_dirs.split()
include_dirs.append(root_dir)
link_flags = "-lswiftest /Users/daminton/git/swiftest/apple_install/usr/local/lib/libnetcdff.a /Users/daminton/git/swiftest/apple_install/usr/local/lib/libnetcdf.a -L/Users/daminton/git/swiftest/apple_install/usr/local/lib -lhdf5_hl -lhdf5 -lm -lz -lbz2 -lxml2 -lcurl"
link_flags = link_flags.split()

pybindings_extension = [Extension('swiftest.bindings',
[os.path.join(root_dir,'pybindings.pyx')],
extra_compile_args=['-fPIC', '-O3','-fopenmp'],
extra_link_args=link_flags,
libraries=['gfortran','omp'],
include_dirs=include_dirs,
)]

setup(name='swiftest',
version='2023.08.00',
author='David A. Minton',
author_email='daminton@purdue.edu',
url='https://github.itap.purdue.edu/MintonGroup/swiftest',
ext_modules = cythonize(pydriver_extension),
ext_modules = cythonize(pybindings_extension),
packages=find_packages())
3 changes: 0 additions & 3 deletions python/swiftest/.idea/.gitignore

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
If not, see: https://www.gnu.org/licenses.
"""

from swiftest.constants import *
from swiftest.simulation_class import Simulation
from constants import *
from simulation_class import Simulation
from bindings import driver
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
34 changes: 17 additions & 17 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
# You should have received a copy of the GNU General Public License along with Swiftest.
# If not, see: https://www.gnu.org/licenses.

########################################
# Set up how to compile the source files
########################################
# Communicate version number and other CMake build variables to the source code
set(GLOBAL_MODULE_IN ${SRC}/globals/globals_module.f90.in)
set(GLOBAL_MODULE_OUT ${SRC}/globals/globals_module.f90)
CONFIGURE_FILE(${GLOBAL_MODULE_IN} ${GLOBAL_MODULE_OUT})

# Add the source files
SET(STRICT_MATH_FILES
Expand Down Expand Up @@ -48,8 +49,7 @@ SET(STRICT_MATH_FILES
${SRC}/whm/whm_gr.f90
${SRC}/whm/whm_kick.f90
${SRC}/whm/whm_step.f90
${PY}/pydriver/src/driver.f90
${PY}/pydriver/src/pydriver.f90
${SRC}/bindings/bindings_module.f90
)

SET(FAST_MATH_FILES
Expand Down Expand Up @@ -96,7 +96,7 @@ SET(COARRAY_FILES

SET(DRIVER_src ${SRC}/main/main.f90)

# Combine all source files (includ)
# Combine all source files
set(SWIFTEST_src ${FAST_MATH_FILES} ${STRICT_MATH_FILES})
IF(USE_COARRAY)
set(SWIFTEST_src ${SWIFTEST_src} ${COARRAY_FILES} )
Expand All @@ -117,20 +117,25 @@ ADD_EXECUTABLE(${SWIFTEST_DRIVER} ${DRIVER_src})
# Add the needed libraries and special compiler flags
#####################################################

TARGET_LINK_LIBRARIES(${SWIFTEST_DRIVER} PRIVATE swiftest ${NETCDF_FORTRAN_LIBRARIES} ${NETCDF_LIBRARIES} $ENV{LIBS})
TARGET_LINK_LIBRARIES(${SWIFTEST_DRIVER} PRIVATE ${SWIFTEST_LIBRARY} ${NETCDF_FORTRAN_LIBRARIES} ${NETCDF_LIBRARIES} $ENV{LIBS})

IF(USE_OPENMP)
SET_PROPERTY(TARGET swiftest ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY COMPILE_FLAGS "${OpenMP_Fortran_FLAGS} ")
SET_PROPERTY(TARGET swiftest ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "${OpenMP_Fortran_FLAGS} ")
SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY COMPILE_FLAGS "${OpenMP_Fortran_FLAGS} ")
SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "${OpenMP_Fortran_FLAGS} ")
ENDIF(USE_OPENMP)

IF(USE_COARRAY)
TARGET_COMPILE_DEFINITIONS(swiftest PRIVATE -DCOARRAY)
TARGET_COMPILE_DEFINITIONS(${SWIFTEST_LIBRARY} PRIVATE -DCOARRAY)
TARGET_COMPILE_DEFINITIONS(${SWIFTEST_DRIVER} PRIVATE -DCOARRAY)
SET_PROPERTY(TARGET swiftest ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY COMPILE_FLAGS "${Coarray_Fortran_FLAGS} ")
SET_PROPERTY(TARGET swiftest ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "${Coarray_Fortran_FLAGS} ")
SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY COMPILE_FLAGS "${Coarray_Fortran_FLAGS} ")
SET_PROPERTY(TARGET ${SWIFTEST_LIBRARY} ${SWIFTEST_DRIVER} APPEND_STRING PROPERTY LINK_FLAGS "${Coarray_Fortran_FLAGS} ")
ENDIF(USE_COARRAY)

STRING(REPLACE ";" " " SWIFTEST_LINK_FLAGS "${CMAKE_LINK_LIBRARY_FLAG}${SWIFTEST_LIBRARY} ${NETCDF_FORTRAN_LIBRARIES} ${NETCDF_LIBRARIES} $ENV{LIBS}")
SET(SWIFTEST_LINK_FLAGS "${SWIFTEST_LINK_FLAGS}" CACHE STRING "Link flags to pass to setup.py")

GET_TARGET_PROPERTY(SWIFTEST_INCLUDE_DIR ${SWIFTEST_DRIVER} INCLUDE_DIRECTORIES)
SET(SWIFTEST_INCLUDE_DIR "${SWIFTEST_INCLUDE_DIR}" CACHE STRING "Include directory needed for linking the library to an executable")

#Set strict vs fast math flags
STRING(TOUPPER "${CMAKE_BUILD_TYPE}" BT)
Expand Down Expand Up @@ -182,8 +187,3 @@ INSTALL(TARGETS ${SWIFTEST_DRIVER} ${SWIFTEST_LIBRARY}
INCLUDES DESTINATION include
)

INSTALL(TARGETS ${SWIFTEST_LIBRARY}
LIBRARY DESTINATION "${PY}/pydriver/lib"
ARCHIVE DESTINATION "${PY}/pydriver/lib"
INCLUDES DESTINATION "${PY}pydriver/include"
)
44 changes: 44 additions & 0 deletions src/bindings/bindings_module.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module bindings_module
use iso_c_binding, only : c_char, c_null_char, c_int
use swiftest, only : swiftest_driver, swiftest_io_get_args, STRMAX
implicit none
contains

subroutine bindings_c2f_string(c_string, f_string)
implicit none
! Arguments
character(len=1,kind=c_char), intent(in) :: c_string(*)
character(len=:), allocatable, intent(out) :: f_string
! Internals
integer :: i
character(len=STRMAX) :: tmp_string

i=1
tmp_string = ''
do while(c_string(i) /= c_null_char .and. i <= STRMAX)
tmp_string(i:i) = c_string(i)
i=i+1
end do

if (i > 1) then
f_string = trim(tmp_string)
else
f_string = ""
end if

return
end subroutine bindings_c2f_string

subroutine bindings_c_driver(c_integrator, c_param_file_name, c_display_style) bind(c)
implicit none
character(kind=c_char), dimension(*), intent(in) :: c_integrator, c_param_file_name, c_display_style
character(len=:), allocatable :: integrator, param_file_name, display_style

call bindings_c2f_string(c_integrator, integrator)
call bindings_c2f_string(c_param_file_name, param_file_name)
call bindings_c2f_string(c_display_style, display_style)

call swiftest_io_get_args(integrator,param_file_name,display_style,from_cli=.false.)
call swiftest_driver(integrator,param_file_name,display_style)
end subroutine bindings_c_driver
end module bindings_module
2 changes: 1 addition & 1 deletion src/main/main.f90
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ program main
character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD"

! Read in command line arguments
call swiftest_io_get_args(integrator, param_file_name, display_style)
call swiftest_io_get_args(integrator, param_file_name, display_style, from_cli=.true.)

! Execute the driver
call swiftest_driver(integrator, param_file_name, display_style)
Expand Down
26 changes: 0 additions & 26 deletions src/python/pydriver/src/driver.f90

This file was deleted.

9 changes: 0 additions & 9 deletions src/python/pydriver/src/pydriver.f90

This file was deleted.

39 changes: 30 additions & 9 deletions src/swiftest/swiftest_io.f90
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ module subroutine swiftest_io_dump_storage(self, param)
end subroutine swiftest_io_dump_storage


module subroutine swiftest_io_get_args(integrator, param_file_name, display_style)
module subroutine swiftest_io_get_args(integrator, param_file_name, display_style, from_cli)
!! author: David A. Minton
!!
!! Reads in the name of the parameter file from command line arguments.
Expand All @@ -455,20 +455,41 @@ module subroutine swiftest_io_get_args(integrator, param_file_name, display_styl
character(len=:), intent(inout), allocatable :: integrator !! Symbolic code of the requested integrator
character(len=:), intent(inout), allocatable :: param_file_name !! Name of the input parameters file
character(len=:), intent(inout), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD"
logical, intent(in) :: from_cli !! If true, get command-line arguments. Otherwise, use the values of the input variables
! Internals
character(len=STRMAX), dimension(:), allocatable :: arg
character(len=STRMAX), dimension(3) :: tmp_arg
integer(I4B), dimension(:), allocatable :: ierr
integer :: i,narg

narg = command_argument_count()
if (narg > 0) then
allocate(arg(narg),ierr(narg))
do i = 1,narg
call get_command_argument(i, arg(i), status = ierr(i))
end do
if (any(ierr /= 0)) call base_util_exit(USAGE)
if (from_cli) then
narg = command_argument_count()
if (narg > 0) then
allocate(arg(narg),ierr(narg))
do i = 1,narg
call get_command_argument(i, arg(i), status = ierr(i))
end do
if (any(ierr /= 0)) call base_util_exit(USAGE)
else
call base_util_exit(USAGE)
end if
else
call base_util_exit(USAGE)
narg = 0
if (len(integrator) > 0) then
narg = narg + 1
tmp_arg(narg) = integrator
end if
if (len(param_file_name) > 0) then
narg = narg + 1
tmp_arg(narg) = param_file_name
end if
if (len(display_style) > 0) then
narg = narg + 1
tmp_arg(narg) = display_style
end if
allocate(arg(narg))
arg(1:narg) = tmp_arg(1:narg)
deallocate(integrator, param_file_name, display_style)
end if

if (narg == 1) then
Expand Down
Loading

0 comments on commit 3957b4b

Please sign in to comment.