diff --git a/Utilities/python_wrapper/CMakeLists.txt b/Utilities/python_wrapper/CMakeLists.txt index 96658fe1..c6850852 100644 --- a/Utilities/python_wrapper/CMakeLists.txt +++ b/Utilities/python_wrapper/CMakeLists.txt @@ -109,11 +109,13 @@ add_custom_target(${f2py_module_name} ALL DEPENDS ${generated_module_file} spec ${f90wrap_output_files} ) +set(f2py_build_dir ${CMAKE_CURRENT_BINARY_DIR}/f2py_build) + add_custom_command( OUTPUT ${generated_module_file} COMMAND ${F2PY_EXECUTABLE} -m ${f2py_module_name} - --build-dir ${CMAKE_CURRENT_BINARY_DIR} + --build-dir ${f2py_build_dir} --f90exec=${CMAKE_Fortran_COMPILER} --f77exec=${CMAKE_Fortran_COMPILER} --f90flags="-fopenmp" @@ -123,7 +125,6 @@ add_custom_command( ${f90wrap_output_files} -I${CMAKE_BINARY_DIR}/build/modules/spec_modules -I${HDF5_Fortran_INCLUDE_DIRS} - --verbose ${CMAKE_BINARY_DIR}/build/lib/libspec.a ${SPEC_LINK_LIB} #IMPLICIT_DEPENDS Fortran ${f90wrap_output_files} @@ -133,9 +134,11 @@ add_custom_command( COMMAND_EXPAND_LISTS ) -python_extension_module(${generated_module_file}) -install(FILES ${python_mod_file} ${generated_module_file} #${CMAKE_CURRENT_SOURCE_DIR}/__init__.py - DESTINATION Utilities/python_wrapper/spec +install(FILES ${python_mod_file} ${generated_module_file} + ${CMAKE_CURRENT_SOURCE_DIR}/spec/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/spec/core.py + DESTINATION spec + COMPONENT python_wrapper ) #set(PYINIT_STR "import sys\nimport os.path\nsys.path.append(os.path.dirname(__file__))\n\nfrom .spec import *\n") diff --git a/Utilities/python_wrapper/cmake/FindF2PY.cmake b/Utilities/python_wrapper/cmake/FindF2PY.cmake new file mode 100644 index 00000000..ebb6230b --- /dev/null +++ b/Utilities/python_wrapper/cmake/FindF2PY.cmake @@ -0,0 +1,38 @@ +# FindF2PY.cmake +# Find f2py executable and include directories + +# Find Python first +find_package(Python COMPONENTS Interpreter Development NumPy REQUIRED) + +# Find f2py executable +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import numpy.f2py; print(numpy.f2py.get_include())" + OUTPUT_VARIABLE F2PY_INCLUDE_DIRS + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +# Find f2py executable path +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import sys; import numpy.f2py as f2py; print(f2py.main.__file__.replace('__main__.py', 'f2py.py') if hasattr(f2py, 'main') else sys.executable + ' -m numpy.f2py')" + OUTPUT_VARIABLE F2PY_EXECUTABLE_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) + +# Set F2PY_EXECUTABLE - use python -m numpy.f2py for reliability +set(F2PY_EXECUTABLE "${Python_EXECUTABLE}" "-m" "numpy.f2py") + +# Set include directories +if(NOT F2PY_INCLUDE_DIRS) + set(F2PY_INCLUDE_DIRS ${Python_NumPy_INCLUDE_DIRS}) +endif() + +# Mark as found if we have Python and NumPy +if(Python_FOUND AND Python_NumPy_FOUND) + set(F2PY_FOUND TRUE) +else() + set(F2PY_FOUND FALSE) +endif() + +mark_as_advanced(F2PY_EXECUTABLE F2PY_INCLUDE_DIRS) \ No newline at end of file diff --git a/Utilities/python_wrapper/cmake/FindNumPy.cmake b/Utilities/python_wrapper/cmake/FindNumPy.cmake new file mode 100644 index 00000000..946bf68e --- /dev/null +++ b/Utilities/python_wrapper/cmake/FindNumPy.cmake @@ -0,0 +1,11 @@ +# FindNumPy.cmake +# Find NumPy include directories + +# Find Python first +find_package(Python COMPONENTS Interpreter NumPy REQUIRED) + +# Set NumPy variables for compatibility +set(NumPy_INCLUDE_DIRS ${Python_NumPy_INCLUDE_DIRS}) +set(NumPy_FOUND ${Python_NumPy_FOUND}) + +mark_as_advanced(NumPy_INCLUDE_DIRS) \ No newline at end of file diff --git a/Utilities/python_wrapper/cmake/FindPythonExtensions.cmake b/Utilities/python_wrapper/cmake/FindPythonExtensions.cmake new file mode 100644 index 00000000..3a034a73 --- /dev/null +++ b/Utilities/python_wrapper/cmake/FindPythonExtensions.cmake @@ -0,0 +1,22 @@ +# FindPythonExtensions.cmake +# Provides functionality for building Python extension modules + +# Find Python +find_package(Python COMPONENTS Interpreter Development REQUIRED) + +# Get the extension suffix +execute_process( + COMMAND ${Python_EXECUTABLE} -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + OUTPUT_VARIABLE PYTHON_EXTENSION_MODULE_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +# Function to mark a target as a Python extension module +function(python_extension_module target) + set_target_properties(${target} PROPERTIES + PREFIX "" + SUFFIX "${PYTHON_EXTENSION_MODULE_SUFFIX}" + ) +endfunction() + +mark_as_advanced(PYTHON_EXTENSION_MODULE_SUFFIX) \ No newline at end of file diff --git a/Utilities/python_wrapper/spec/__init__.py b/Utilities/python_wrapper/spec/__init__.py index 183e796b..56b6c816 100644 --- a/Utilities/python_wrapper/spec/__init__.py +++ b/Utilities/python_wrapper/spec/__init__.py @@ -1,10 +1,8 @@ import os.path -#print(__file__) -#print(os.path.dirname(__file__)) -path_to_spec_f90wrapped = os.path.dirname(__file__) - import sys -if not path_to_spec_f90wrapped in sys.path: - sys.path.append(path_to_spec_f90wrapped) -# import spec_f90wrapped as spec +# Add current directory to path if not already there +path_to_spec_f90wrapped = os.path.dirname(__file__) +if path_to_spec_f90wrapped not in sys.path: + sys.path.append(path_to_spec_f90wrapped) + diff --git a/cmake_config.json b/cmake_config.json deleted file mode 120000 index 4f8229e4..00000000 --- a/cmake_config.json +++ /dev/null @@ -1 +0,0 @@ -cmake_machines/conda_debian.json \ No newline at end of file diff --git a/cmake_machines/centos7_default.json b/cmake_machines/centos7_default.json deleted file mode 100644 index acbe200d..00000000 --- a/cmake_machines/centos7_default.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_CXX_COMPILER=mpicxx", - "-DCMAKE_Fortran_COMPILER=mpifort", - "-DBLA_VENDOR=OpenBLAS", - "-DHDF5_NO_FIND_PACKAGE_CONFIG_FILE=TRUE", - "-DHDF5_PREFER_PARALLEL=TRUE"] -} diff --git a/cmake_machines/conda.json b/cmake_machines/conda.json deleted file mode 100644 index 4f5c4e81..00000000 --- a/cmake_machines/conda.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_CXX_COMPILER=mpicxx", - "-DCMAKE_Fortran_COMPILER=mpifort", - "-DBLA_VENDOR=OpenBLAS", - "-DHDF5_ROOT=~/opt/miniconda3/envs/simsopt/", - "-DHDF5_PREFER_PARALLEL=TRUE"] -} diff --git a/cmake_machines/conda_debian.json b/cmake_machines/conda_debian.json deleted file mode 100644 index db76bf76..00000000 --- a/cmake_machines/conda_debian.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_Fortran_COMPILER=mpif90", - "-DBLA_VENDOR=OpenBLAS" - ] -} diff --git a/cmake_machines/gfortran_arch.json b/cmake_machines/gfortran_arch.json deleted file mode 100644 index 3cea61a1..00000000 --- a/cmake_machines/gfortran_arch.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_CXX_COMPILER=mpicxx", - "-DCMAKE_Fortran_COMPILER=mpif90", - "-DHDF5_PREFER_PARALLEL=False"] -} diff --git a/cmake_machines/gfortran_debian.json b/cmake_machines/gfortran_debian.json deleted file mode 100644 index 1f35f7bb..00000000 --- a/cmake_machines/gfortran_debian.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_Fortran_COMPILER=mpif90", - "-DHDF5_ROOT=/usr/lib/x86_64-linux-gnu/hdf5/serial" - ] -} diff --git a/cmake_machines/gfortran_ubuntu.json b/cmake_machines/gfortran_ubuntu.json deleted file mode 100644 index 80ec61e3..00000000 --- a/cmake_machines/gfortran_ubuntu.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_CXX_COMPILER=mpicxx", - "-DCMAKE_Fortran_COMPILER=mpifort", - "-DBLA_VENDOR=OpenBLAS", - "-DHDF5_ROOT=/usr/lib/x86_64-linux-gnu/hdf5/serial", - "-DHDF5_PREFER_PARALLEL=False"] -} diff --git a/cmake_machines/intel_SUSE.json b/cmake_machines/intel_SUSE.json deleted file mode 100644 index 398c9534..00000000 --- a/cmake_machines/intel_SUSE.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "cmake_args": [ - "-DCMAKE_C_COMPILER=mpicc", - "-DCMAKE_CXX_COMPILER=mpicc", - "-DCMAKE_Fortran_COMPILER=mpif90", - "-DBLA_VENDOR=Intel10_64lp" - ] -} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..3be479d0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,67 @@ +[build-system] +requires = [ + "scikit-build-core>=0.8.0", + "numpy>=2.2", + "f90wrap", + "meson;python_version>='3.12'", + "ninja" +] +build-backend = "scikit_build_core.build" + +[project] +name = "spec" +version = "0.0.3" +description = "Stepped Pressure Equilibrium Code MHD Equilibrium Solver" +authors = [ + {name = "Christopher Berg Smiet", email = "christopher.smiet@epfl.ch"}, + {name = "Stuart R. Hudson"}, + {name = "Joaquim Loizu", email = "joaquim.loizu@epfl.ch"}, + {name = "Bharat Medasani", email = "mbkumar@gmail.com"}, + {name = "Caoxiang Zhu"} +] +readme = "README.md" +license = {file = "LICENSE"} +requires-python = ">=3.8" +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GPL-3.0 License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Physics", +] +dependencies = [ + "numpy>=1.23.5", + "f90wrap", +] + + +[project.urls] +Homepage = "https://github.com/PrincetonUniversity/SPEC" +Documentation = "https://princetonuniversity.github.io/SPEC/" +Repository = "https://github.com/PrincetonUniversity/SPEC.git" +"Bug Tracker" = "https://github.com/PrincetonUniversity/SPEC/issues" + +[tool.scikit-build] +# Specify the CMake source directory +cmake.source-dir = "." +# Set minimum CMake version +cmake.version = ">=3.15" +# Build directory +build-dir = "build/{wheel_tag}" +# Configure install components +install.components = ["python_wrapper"] +# Ensure wheel includes the Python wrapper package +wheel.packages = ["spec"] + +[tool.scikit-build.cmake.define] +# Ensure SKBUILD is defined for conditional Python wrapper building +SKBUILD = "ON" +# Set compilers and BLAS vendor from cmake_config.json +CMAKE_C_COMPILER = {env="CMAKE_ARGS_CMAKE_C_COMPILER", default="mpicc"} +CMAKE_Fortran_COMPILER = {env="CMAKE_ARGS_CMAKE_Fortran_COMPILER", default="mpif90"} +BLA_VENDOR = {env="CMAKE_ARGS_BLA_VENDOR", default="OpenBLAS"} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 387457d8..718c321b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -295,6 +295,16 @@ endif() add_executable(xspec ${XSPEC_OUT_FILE}) target_link_libraries(xspec PUBLIC spec) + +# Ensure MPI and OpenMP are linked to xspec executable +if(MPI_Fortran_FOUND) + target_link_libraries(xspec PUBLIC MPI::MPI_Fortran) +endif() + +if(OpenMP_Fortran_FOUND) + target_link_libraries(xspec PUBLIC OpenMP::OpenMP_Fortran) +endif() + set_target_properties(xspec PROPERTIES POSITION_INDEPENDENT_CODE ON) install(TARGETS xspec spec)