diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index faca3472..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,8 +0,0 @@ -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" # Location of package manifests - schedule: - interval: "weekly" - diff --git a/.github/workflows/CI_C_API.yml.bak b/.github/workflows/CI_C_API.yml.bak deleted file mode 100644 index bc6211c6..00000000 --- a/.github/workflows/CI_C_API.yml.bak +++ /dev/null @@ -1,76 +0,0 @@ -# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage. -# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml -name: Build C_API and run tests with Julia - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - CCACHE_BASEDIR: ${GITHUB_WORKSPACE} - CCACHE_DIR: ${GITHUB_WORKSPACE}/.ccache - CCACHE_COMPRESS: true - CCACHE_COMPRESSLEVEL: 5 - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Install ccache - run: sudo apt install ccache - - name: Install Eigen - run: sudo apt install libeigen3-dev - - - name: libsparseir cache restore - id: build-c-api - uses: actions/cache/restore@v4 - with: - path: .ccache - key: ${{ runner.os }}-pipelines-${{ hashFiles('src/cinterface.cpp') }} - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: | - cmake -B ${{github.workspace}}/build \ - -DSPARSEIR_BUILD_TESTING=OFF \ - -DSPARSEIR_BUILD_FORTRAN=OFF \ - -DCMAKE_INSTALL_PREFIX="$HOME/opt/libsparseir" \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -DCCACHE_DIR=${{env.CCACHE_DIR}} \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - name: Install - # Install your program with the given configuration - run: cmake --install ${{github.workspace}}/build - - - name: libsparseir cache save - id: cache-pipelines - uses: actions/cache/save@v4 - env: - cache-name: cache-pipelines - with: - key: ${{ runner.os }}-pipelines-${{ hashFiles('src/cinterface.cpp') }} - path: .ccache - - - uses: julia-actions/setup-julia@v2 - - uses: julia-actions/cache@v2 - - uses: julia-actions/julia-buildpkg@v1 - with: - project: ${{github.workspace}}/julia - - uses: julia-actions/julia-runtest@v1 - with: - project: ${{github.workspace}}/julia diff --git a/.github/workflows/CI_C_API_Julia.yml.bak b/.github/workflows/CI_C_API_Julia.yml.bak deleted file mode 100644 index d2dfea00..00000000 --- a/.github/workflows/CI_C_API_Julia.yml.bak +++ /dev/null @@ -1,76 +0,0 @@ -# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage. -# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml -name: Build C_API and run tests with Julia - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - CCACHE_BASEDIR: ${GITHUB_WORKSPACE} - CCACHE_DIR: ${GITHUB_WORKSPACE}/.ccache - CCACHE_COMPRESS: true - CCACHE_COMPRESSLEVEL: 5 - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Install ccache - run: sudo apt install ccache - - name: Install Eigen - run: sudo apt install libeigen3-dev - - - name: libsparseir cache restore - id: build-c-api - uses: actions/cache/restore@v4 - with: - path: ${{env.CCACHE_DIR }} - key: ${{ runner.os }}-pipelines-${{ hashFiles('src/cinterface.cpp') }} - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: | - cmake -B ${{github.workspace}}/build \ - -DSPARSEIR_BUILD_TESTING=OFF \ - -DSPARSEIR_BUILD_FORTRAN=OFF \ - -DCMAKE_INSTALL_PREFIX="$HOME/opt/libsparseir" \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -DCCACHE_DIR=${{env.CCACHE_DIR}} \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - name: Install - # Install your program with the given configuration - run: cmake --install ${{github.workspace}}/build - - - name: libsparseir cache save - id: cache-pipelines - uses: actions/cache/save@v4 - env: - cache-name: cache-pipelines - with: - key: ${{ steps.build-c-api.outputs.cache-primary-key }} - path: ${{env.CCACHE_DIR }} - - - uses: julia-actions/setup-julia@v2 - - uses: julia-actions/cache@v2 - - uses: julia-actions/julia-buildpkg@v1 - with: - project: ${{github.workspace}}/julia - - uses: julia-actions/julia-runtest@v1 - with: - project: ${{github.workspace}}/julia diff --git a/.github/workflows/CI_C_API_Python.yml b/.github/workflows/CI_C_API_Python.yml index 2e0aef65..5791cbbb 100644 --- a/.github/workflows/CI_C_API_Python.yml +++ b/.github/workflows/CI_C_API_Python.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies (macOS) if: runner.os == 'macOS' run: brew install eigen openblas - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install uv and set the python version uses: astral-sh/setup-uv@v6 with: diff --git a/.github/workflows/CI_PublishTestPyPI.yml b/.github/workflows/CI_PublishTestPyPI.yml index 106d7168..f80200b2 100644 --- a/.github/workflows/CI_PublishTestPyPI.yml +++ b/.github/workflows/CI_PublishTestPyPI.yml @@ -3,8 +3,6 @@ name: CI Python Build & Publish to TestPyPI (Trusted) on: push: tags: ["v*"] - pull_request: - branches: [main] workflow_dispatch: jobs: diff --git a/.github/workflows/CI_cmake.yml b/.github/workflows/CI_cmake.yml deleted file mode 100644 index 0554c6e7..00000000 --- a/.github/workflows/CI_cmake.yml +++ /dev/null @@ -1,246 +0,0 @@ -# Multi-platform CMake CI workflow for libsparseir -# Tests across Windows, macOS, and Ubuntu with gcc and clang compilers -name: CMake Multi-Platform CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - INSTALL_PREFIX: ${{github.workspace}}/install - -jobs: - build: - strategy: - fail-fast: false - matrix: - include: - # Ubuntu with gcc and clang - - os: ubuntu-latest - compiler: gcc - c_compiler: gcc - cpp_compiler: g++ - eigen_install: sudo apt update && sudo apt install -y libeigen3-dev - - os: ubuntu-latest - compiler: clang - c_compiler: clang - cpp_compiler: clang++ - eigen_install: sudo apt update && sudo apt install -y libeigen3-dev - - # macOS with gcc and clang - #- os: macos-latest - #compiler: gcc - #c_compiler: gcc-15 - #cpp_compiler: g++-15 - #eigen_install: brew install eigen - - os: macos-latest - compiler: clang - c_compiler: clang - cpp_compiler: clang++ - eigen_install: brew install eigen - - # Windows with MSVC and clang - #- os: windows-latest - # compiler: msvc - # c_compiler: cl - # cpp_compiler: cl - # eigen_install: vcpkg install eigen3 - #- os: windows-latest - # compiler: clang - # c_compiler: clang - # cpp_compiler: clang++ - # eigen_install: vcpkg install eigen3 - - runs-on: ${{ matrix.os }} - name: ${{ matrix.os }}-${{ matrix.compiler }} - - steps: - - uses: actions/checkout@v5 - - - name: Set up MSVC (Windows) - if: matrix.os == 'windows-latest' && matrix.compiler == 'msvc' - uses: microsoft/setup-msbuild@v2 - - - name: Setup vcpkg (Windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: | - git clone https://github.com/Microsoft/vcpkg.git - .\vcpkg\bootstrap-vcpkg.bat - "${{ github.workspace }}\vcpkg" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Install Fortran compiler (macOS) - if: matrix.os == 'macos-latest' - run: brew install gfortran - - - name: Install Eigen - run: ${{ matrix.eigen_install }} - - - name: Debug Fortran compilers (macOS) - if: matrix.os == 'macos-latest' - run: | - echo "Available Fortran compilers:" - ls -la /opt/homebrew/bin/*fortran* || echo "No *fortran* found in /opt/homebrew/bin/" - ls -la /usr/local/bin/*fortran* || echo "No *fortran* found in /usr/local/bin/" - which gfortran || echo "gfortran not in PATH" - which gfortran-13 || echo "gfortran-13 not in PATH" - - - name: Configure CMake (Unix) - if: matrix.os != 'windows-latest' - run: | - if [[ "${{ matrix.os }}" == "macos-latest" ]]; then - # Use the full path to gfortran from Homebrew gcc - FORTRAN_COMPILER="/opt/homebrew/bin/gfortran-13" - else - FORTRAN_COMPILER="gfortran" - fi - - cmake -B ${{github.workspace}}/build \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_Fortran_COMPILER=$FORTRAN_COMPILER \ - -DSPARSEIR_BUILD_TESTING=ON \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -DSPARSEIR_BUILD_FORTRAN=ON \ - -DCMAKE_INSTALL_PREFIX=${{env.INSTALL_PREFIX}} \ - -DSPARSEIR_USE_BLAS=OFF - - - name: Configure CMake (Windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: | - cmake -B ${{github.workspace}}/build ` - -DCMAKE_TOOLCHAIN_FILE="${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake" ` - -DSPARSEIR_BUILD_TESTING=ON ` - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ` - -DSPARSEIR_BUILD_FORTRAN=OFF ` - -DCMAKE_INSTALL_PREFIX=${{env.INSTALL_PREFIX}} ` - -DSPARSEIR_USE_BLAS=OFF - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Test - working-directory: ${{github.workspace}}/build - run: ctest --output-on-failure --build-config ${{env.BUILD_TYPE}} - - - name: Install - run: cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Run test samples (Unix) - if: matrix.os != 'windows-latest' - run: | - cd sample_c - cmake -B build -DSparseIR_DIR=${{env.INSTALL_PREFIX}}/share/cmake/SparseIR - cmake --build build - cmake --build build --target test - - - name: Run test samples (Windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: | - cd sample_c - cmake -B build -DSparseIR_DIR="${{env.INSTALL_PREFIX}}/share/cmake/SparseIR" - cmake --build build --config ${{env.BUILD_TYPE}} - cmake --build build --target test --config ${{env.BUILD_TYPE}} - - - name: Run benchmark (Unix) - if: matrix.os != 'windows-latest' - run: | - cd benchmark - cmake -B build -DSparseIR_DIR=${{env.INSTALL_PREFIX}}/share/cmake/SparseIR - cmake --build build - cmake --build build --target test - - - name: Run benchmark (Windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: | - cd benchmark - cmake -B build -DSparseIR_DIR="${{env.INSTALL_PREFIX}}/share/cmake/SparseIR" - cmake --build build --config ${{env.BUILD_TYPE}} - cmake --build build --target test --config ${{env.BUILD_TYPE}} - - - build_with_blas: - strategy: - fail-fast: false - matrix: - include: - # Ubuntu with gcc and clang (BLAS/LAPACK enabled) - - os: ubuntu-latest - compiler: gcc - c_compiler: gcc - cpp_compiler: g++ - deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev - - os: ubuntu-latest - compiler: clang - c_compiler: clang - cpp_compiler: clang++ - deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev - - # macOS with gcc and clang (BLAS/LAPACK enabled) - #- os: macos-latest - #compiler: gcc - #c_compiler: gcc-13 - #cpp_compiler: g++-13 - #deps_install: brew install eigen openblas lapack - - os: macos-latest - compiler: clang - c_compiler: clang - cpp_compiler: clang++ - deps_install: brew install eigen openblas lapack - - runs-on: ${{ matrix.os }} - name: ${{ matrix.os }}-${{ matrix.compiler }}-blas - - steps: - - uses: actions/checkout@v5 - - - name: Install Fortran compiler (macOS) - if: matrix.os == 'macos-latest' - run: brew install gfortran - - - name: Install dependencies - run: ${{ matrix.deps_install }} - - - name: Configure CMake - run: | - if [[ "${{ matrix.os }}" == "macos-latest" ]]; then - # Use the full path to gfortran from Homebrew gcc - FORTRAN_COMPILER="/opt/homebrew/bin/gfortran-13" - else - FORTRAN_COMPILER="gfortran" - fi - - cmake -B ${{github.workspace}}/build \ - -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ - -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ - -DCMAKE_Fortran_COMPILER=$FORTRAN_COMPILER \ - -DSPARSEIR_BUILD_TESTING=ON \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -DSPARSEIR_BUILD_FORTRAN=ON \ - -DCMAKE_INSTALL_PREFIX=${{env.INSTALL_PREFIX}} \ - -DSPARSEIR_USE_BLAS=ON - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Test - working-directory: ${{github.workspace}}/build - run: ctest --output-on-failure --build-config ${{env.BUILD_TYPE}} - - - name: Install - run: cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Run test samples - run: | - cd sample_c - cmake -B build -DSparseIR_DIR=${{env.INSTALL_PREFIX}}/share/cmake/SparseIR - cmake --build build - cmake --build build --target test - diff --git a/.github/workflows/CI_cmake_with_blas.yml b/.github/workflows/CI_cmake_with_blas.yml new file mode 100644 index 00000000..63d36e15 --- /dev/null +++ b/.github/workflows/CI_cmake_with_blas.yml @@ -0,0 +1,185 @@ +# Multi-platform CMake CI workflow for libsparseir (with BLAS/OpenBLAS) +# Tests across Ubuntu and macOS with BLAS/LAPACK support +name: CMake Multi-Platform CI (With BLAS) + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + INSTALL_PREFIX: ${{github.workspace}}/install + +jobs: + build-with-blas: + strategy: + fail-fast: false + matrix: + include: + # Ubuntu with gcc and clang (BLAS/LAPACK enabled) - x86_64 + #- os: ubuntu-latest + #compiler: gcc + #c_compiler: gcc + #cpp_compiler: g++ + #deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev + #- os: ubuntu-latest + #compiler: clang + #c_compiler: clang + #cpp_compiler: clang++ + #deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev + + # Ubuntu ARM64 with gcc and clang (BLAS/LAPACK enabled) + #- os: ubuntu-latest + #arch: arm64 + #compiler: gcc + #c_compiler: gcc + #cpp_compiler: g++ + #deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev + #- os: ubuntu-latest + #arch: arm64 + #compiler: clang + #c_compiler: clang + #cpp_compiler: clang++ + #deps_install: sudo apt update && sudo apt install -y libeigen3-dev libblas-dev liblapack-dev + + # macOS with BLAS (using Accelerate framework) + - os: macos-latest + compiler: clang + c_compiler: clang + cpp_compiler: clang++ + blas_type: accelerate + deps_install: brew install eigen + + # macOS with OpenBLAS + - os: macos-latest + compiler: clang + c_compiler: clang + cpp_compiler: clang++ + blas_type: openblas + deps_install: brew install eigen openblas + + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }}-${{ matrix.compiler }}${{ matrix.arch && format('-{0}', matrix.arch) || '' }}${{ matrix.blas_type && format('-{0}', matrix.blas_type) || '' }}-blas + + steps: + - uses: actions/checkout@v5 + + - name: Install Fortran compiler (macOS) + if: matrix.os == 'macos-latest' + run: brew install gfortran + + - name: Install dependencies + run: ${{ matrix.deps_install }} + + - name: Debug Fortran compilers (macOS) + if: matrix.os == 'macos-latest' + run: | + echo "Available Fortran compilers:" + ls -la /opt/homebrew/bin/*fortran* || echo "No *fortran* found in /opt/homebrew/bin/" + ls -la /usr/local/bin/*fortran* || echo "No *fortran* found in /usr/local/bin/" + which gfortran || echo "gfortran not in PATH" + which gfortran-13 || echo "gfortran-13 not in PATH" + + - name: Configure CMake + run: | + if [[ "${{ matrix.os }}" == "macos-latest" ]]; then + # Use the full path to gfortran from Homebrew gcc + FORTRAN_COMPILER="/opt/homebrew/bin/gfortran-13" + + # Set OpenBLAS paths for macOS if using OpenBLAS + if [[ "${{ matrix.blas_type }}" == "openblas" ]]; then + OPENBLAS_ROOT="/opt/homebrew/opt/openblas" + export LDFLAGS="-L${OPENBLAS_ROOT}/lib" + export CPPFLAGS="-I${OPENBLAS_ROOT}/include" + export PKG_CONFIG_PATH="${OPENBLAS_ROOT}/lib/pkgconfig" + fi + else + FORTRAN_COMPILER="gfortran" + fi + + cmake -B ${{github.workspace}}/build \ + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} \ + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} \ + -DCMAKE_Fortran_COMPILER="$FORTRAN_COMPILER" \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ + -DSPARSEIR_BUILD_FORTRAN=ON \ + -DCMAKE_INSTALL_PREFIX=${{env.INSTALL_PREFIX}} \ + -DSPARSEIR_BUILD_TESTING=ON \ + -DSPARSEIR_USE_BLAS=ON + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + run: ctest --build-config ${{env.BUILD_TYPE}} --output-on-failure + + - name: Install + run: cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Verify Installation + run: | + ls -la ${{env.INSTALL_PREFIX}}/include/sparseir/ + ls -la ${{env.INSTALL_PREFIX}}/lib/ + + - name: Check BLAS linking + run: | + if [[ "${{ matrix.os }}" == "macos-latest" ]]; then + otool -L ${{env.INSTALL_PREFIX}}/lib/libsparseir.dylib | grep -E "(Accelerate|openblas)" || echo "No BLAS library found in linking" + else + ldd ${{env.INSTALL_PREFIX}}/lib/libsparseir.so | grep -E "(blas|lapack|openblas)" || echo "No BLAS library found in linking" + fi + + - name: Build and Run Fortran Sample + run: | + echo "=== Building Fortran Sample ===" + cd fortran/sample + + # Find SparseIR CMake config + SPARSEIR_DIR="${{env.INSTALL_PREFIX}}/share/cmake/SparseIR" + if [ ! -d "$SPARSEIR_DIR" ]; then + echo "ERROR: SparseIR CMake config not found at $SPARSEIR_DIR" + exit 1 + fi + + # Install FFTW3 if needed + if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then + sudo apt-get update && sudo apt-get install -y libfftw3-dev + elif [[ "${{ matrix.os }}" == "macos-latest" ]]; then + # FFTW3 might already be installed via deps_install, but ensure it's available + brew list fftw || brew install fftw + fi + + # Clean and build + rm -rf build + + # Set Fortran compiler explicitly + if [[ "${{ matrix.os }}" == "macos-latest" ]]; then + FORTRAN_COMPILER="/opt/homebrew/bin/gfortran-13" + else + FORTRAN_COMPILER="gfortran" + fi + + cmake -B build \ + -DSparseIR_DIR="$SPARSEIR_DIR" \ + -DUSE_SYSTEM_LIBSPARSEIR=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_Fortran_COMPILER="$FORTRAN_COMPILER" + + cmake --build build + + echo "=== Running Fortran Sample ===" + + export LD_LIBRARY_PATH="${{env.INSTALL_PREFIX}}/lib:$LD_LIBRARY_PATH" + export DYLD_LIBRARY_PATH="${{env.INSTALL_PREFIX}}/lib:$DYLD_LIBRARY_PATH" + echo "Set library paths:" + echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" + echo "DYLD_LIBRARY_PATH: $DYLD_LIBRARY_PATH" + + ./build/second_order_perturbation_fort + + echo "=== Fortran Sample completed successfully ===" + diff --git a/.github/workflows/CI_dist.yml.bak b/.github/workflows/CI_dist.yml.bak deleted file mode 100644 index 027c0ba8..00000000 --- a/.github/workflows/CI_dist.yml.bak +++ /dev/null @@ -1,71 +0,0 @@ -name: Build and Test - -on: - pull_request: - branches: [ main ] - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - compiler: [gcc, clang] - include: - - os: ubuntu-latest - compiler: gcc - cxx: g++ - fc: gfortran - - os: ubuntu-latest - compiler: clang - cxx: clang++ - fc: gfortran - - os: macos-latest - compiler: gcc - cxx: g++-13 - fc: gfortran - - os: macos-latest - compiler: clang - cxx: clang++ - fc: gfortran - - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies (Ubuntu) - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y gfortran - - - name: Install dependencies (macOS) - if: runner.os == 'macOS' - run: | - brew install gfortran - if [ "${{ matrix.compiler }}" = "gcc" ]; then - brew install gcc@13 - fi - - - name: Create distribution - run: | - cd bundle - ./build.sh - - - name: Build C++ library - run: | - cd bundle/dist - cd libsparseir-*/ - make CXX=${{ matrix.cxx }} - - - name: Build Fortran library - run: | - cd bundle/dist - cd libsparseir-*/ - make fortran FC=${{ matrix.fc }} - - - name: Install libraries - run: | - cd bundle/dist - cd libsparseir-*/ - make install - make install-fortran \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4e62c27e..52fac89e 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,14 @@ latex # Generated test files testsample/readme_samples_test.cpp fortran/test/readme_samples_test.f90 + +# Python +__pycache__/ +*.py[cod] +*.egg-info/ +dist/ +.venv/ +python/src/ +python/pylibsparseir/*.dylib +python/pylibsparseir/*.so +python/pylibsparseir/*.dll diff --git a/fortran/pyproject.toml b/fortran/pyproject.toml deleted file mode 100644 index e49e1f26..00000000 --- a/fortran/pyproject.toml +++ /dev/null @@ -1,9 +0,0 @@ -[project] -name = "fortran" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" -requires-python = ">=3.10" -dependencies = [ - "clang>=20.1.5", -] diff --git a/fortran/sample/CMakeLists.txt b/fortran/sample/CMakeLists.txt index 6756bbf7..46bd24d2 100644 --- a/fortran/sample/CMakeLists.txt +++ b/fortran/sample/CMakeLists.txt @@ -44,6 +44,15 @@ find_path(FFTW3_INCLUDE_DIR fftw3.f) # Create a simple Fortran test add_executable(second_order_perturbation_fort second_order_perturbation_fort.f90) +# Set RPATH for both Linux and macOS +set_target_properties(second_order_perturbation_fort PROPERTIES + INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" + BUILD_RPATH "${CMAKE_INSTALL_PREFIX}/lib" + INSTALL_RPATH_USE_LINK_PATH TRUE + # macOS specific: use @rpath for better portability + MACOSX_RPATH TRUE +) + # Link with libsparseir target_link_libraries(second_order_perturbation_fort PRIVATE SparseIR::sparseir_fortran ${FFTW3_LIB}) diff --git a/fortran/sample/second_order_perturbation_fort.f90 b/fortran/sample/second_order_perturbation_fort.f90 index fa89c262..155887b9 100644 --- a/fortran/sample/second_order_perturbation_fort.f90 +++ b/fortran/sample/second_order_perturbation_fort.f90 @@ -44,23 +44,23 @@ SUBROUTINE read_input nk_lin = 256 hubbardu = 2.0E0_DP ! - READ(5,NML=input,IOSTAT=ios) - IF(ios.NE.0) THEN - PRINT*, 'ERROR in read_input: reading namelist input' - STOP - ENDIF + !READ(5,NML=input,IOSTAT=ios) + !IF(ios.NE.0) THEN + !PRINT*, 'ERROR in read_input: reading namelist input' + !STOP + !ENDIF ! - rdum = LOG(lambda) / LOG(1.0E1_DP) - IF ( ABS(rdum - NINT(rdum)) > 1.0E-8_DP ) THEN - PRINT*, 'ERROR in read_input: lambda is not a positive integer power of 10.' - STOP - ENDIF + !rdum = LOG(lambda) / LOG(1.0E1_DP) + !IF ( ABS(rdum - NINT(rdum)) > 1.0E-8_DP ) THEN + !PRINT*, 'ERROR in read_input: lambda is not a positive integer power of 10.' + !!STOP + !ENDIF ! - rdum = LOG(eps) / LOG(1.0E-1_DP) - IF ( ABS(rdum - NINT(rdum)) > 1.0E-8_DP ) THEN - PRINT*, 'ERROR in read_input: eps is not a positive integer power of 0.1.' - STOP - ENDIF + !rdum = LOG(eps) / LOG(1.0E-1_DP) + !IF ( ABS(rdum - NINT(rdum)) > 1.0E-8_DP ) THEN + !PRINT*, 'ERROR in read_input: eps is not a positive integer power of 0.1.' + !STOP + !ENDIF ! END SUBROUTINE read_input ! diff --git a/fortran/uv.lock b/fortran/uv.lock deleted file mode 100644 index ed540cb9..00000000 --- a/fortran/uv.lock +++ /dev/null @@ -1,23 +0,0 @@ -version = 1 -revision = 1 -requires-python = ">=3.10" - -[[package]] -name = "clang" -version = "20.1.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/55/39db28e9b95c6ed49b5fce40878e034961d05dcda7d26347392af6755d28/clang-20.1.5.tar.gz", hash = "sha256:1395dc8f51a4542644356cacae482d797b2e1b3f72ab7674af42de593a3dff7f", size = 8605 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/bd/8410abff6b094f42e702745c90bb869cd78b66212aad1d5ccf4ebdfc4ad9/clang-20.1.5-py3-none-any.whl", hash = "sha256:b816c582ee8d230a7591386569cfb9311bf67339136aed7fd48264009da9c0b3", size = 38983 }, -] - -[[package]] -name = "fortran" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "clang" }, -] - -[package.metadata] -requires-dist = [{ name = "clang", specifier = ">=20.1.5" }] diff --git a/include/sparseir/impl/poly_impl.hpp b/include/sparseir/impl/poly_impl.hpp index 1a36e408..3a12dd10 100644 --- a/include/sparseir/impl/poly_impl.hpp +++ b/include/sparseir/impl/poly_impl.hpp @@ -59,13 +59,17 @@ func_for_part(const PiecewiseLegendreFT &polyFT, if (part == nullptr) { int parity = polyFT.poly.get_symm(); if (parity == 1) { - part = std::is_same::value - ? [](std::complex x) { return x.real(); } - : [](std::complex x) { return x.imag(); }; + if (std::is_same::value) { + part = [](std::complex x) { return x.real(); }; + } else { + part = [](std::complex x) { return x.imag(); }; + } } else if (parity == -1) { - part = std::is_same::value - ? [](std::complex x) { return x.imag(); } - : [](std::complex x) { return x.real(); }; + if (std::is_same::value) { + part = [](std::complex x) { return x.imag(); }; + } else { + part = [](std::complex x) { return x.real(); }; + } } else { throw std::runtime_error("Cannot detect parity"); } diff --git a/include/sparseir/impl/sve_impl.hpp b/include/sparseir/impl/sve_impl.hpp index a3812dd9..02a95e6a 100644 --- a/include/sparseir/impl/sve_impl.hpp +++ b/include/sparseir/impl/sve_impl.hpp @@ -481,7 +481,7 @@ SVEResult compute_sve(const K &kernel, double epsilon, double cutoff, int lmax, std::string Twork_actual; std::string svd_strategy_actual; std::tie(safe_epsilon, Twork_actual, svd_strategy_actual) = - sparseir::auto_choose_accuracy(epsilon, Twork); + sparseir::auto_choose_accuracy(epsilon, Twork, "auto"); if (Twork_actual == "Float64") { return std::get<0>(pre_postprocess(kernel, safe_epsilon, diff --git a/include/sparseir/sparseir.h b/include/sparseir/sparseir.h index 81b18476..93fced7b 100644 --- a/include/sparseir/sparseir.h +++ b/include/sparseir/sparseir.h @@ -1,13 +1,19 @@ #pragma once #include -#include #include -#include "spir_status.h" - +#ifdef _MSC_VER +// MSVC doesn't support C99 complex types by default +#include +typedef std::complex c_complex; +#else +#include // Define a C-compatible type alias for the C99 complex number. typedef double _Complex c_complex; +#endif + +#include "spir_status.h" // Status codes #define SPIR_COMPUTATION_SUCCESS 0 diff --git a/python/.gitignore b/python/.gitignore deleted file mode 100644 index 32a7b905..00000000 --- a/python/.gitignore +++ /dev/null @@ -1,231 +0,0 @@ - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[codz] -*$py.class - -# C extensions -*.so -*.dylib -*.dll - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py.cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock -#poetry.toml - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. -# https://pdm-project.org/en/latest/usage/project/#working-with-version-control -#pdm.lock -#pdm.toml -.pdm-python -.pdm-build/ - -# pixi -# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. -#pixi.lock -# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one -# in the .venv directory. It is recommended not to include this directory in version control. -.pixi - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.envrc -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Abstra -# Abstra is an AI-powered process automation framework. -# Ignore directories containing user credentials, local state, and settings. -# Learn more at https://abstra.io/docs -.abstra/ - -# Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore -# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, -# you could uncomment the following to ignore the entire vscode folder -# .vscode/ - -# Ruff stuff: -.ruff_cache/ - -# PyPI configuration file -.pypirc - -# Cursor -# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to -# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data -# refer to https://docs.cursor.com/context/ignore-files -.cursorignore -.cursorindexingignore - -# Marimo -marimo/_static/ -marimo/_lsp/ -__marimo__/ - -# Project specific -# Test files in root directory -/test_*.py -/api.py -/demo_api.py - -# Compiled libraries -pylibsparseir/*.dylib -pylibsparseir/*.so -pylibsparseir/*.dll - -# generated files by setup.py -src/**/*.cpp -src/**/*.hpp -include -fortran -LICENSE -CMakeLists.txt -setup_build.py -cmake \ No newline at end of file diff --git a/python/setup.py b/python/setup.py index ec4a788a..d5edc8f2 100644 --- a/python/setup.py +++ b/python/setup.py @@ -473,6 +473,17 @@ def run(self): print(f"Extension modules: {ext_modules}", flush=True) +# Run setup_build.py before setup() to ensure source files are available +# This runs in the original directory before any temporary directories are created +print("Running setup_build.py to prepare source files...", flush=True) +try: + import subprocess + subprocess.check_call([sys.executable, 'setup_build.py']) + print("setup_build.py completed successfully", flush=True) +except Exception as e: + print(f"Warning: setup_build.py failed: {e}", flush=True) + # Continue anyway - files might already be available + setup( package_dir={'': './'}, packages=['pylibsparseir'], diff --git a/src/cinterface_impl/helper_funcs.hpp b/src/cinterface_impl/helper_funcs.hpp index 635d8388..96a75e8d 100644 --- a/src/cinterface_impl/helper_funcs.hpp +++ b/src/cinterface_impl/helper_funcs.hpp @@ -4,6 +4,7 @@ #include #include #include "_util.hpp" +#include "sparseir/sparseir.h" inline bool is_dlr_basis(const spir_basis *b) { return std::dynamic_pointer_cast>(get_impl_basis(b)) != nullptr || diff --git a/src/sve.cpp b/src/sve.cpp index 5bcce0bb..b1587df5 100644 --- a/src/sve.cpp +++ b/src/sve.cpp @@ -24,12 +24,12 @@ SVEResult::part(double eps, int max_size) const eps = std::isnan(eps) ? this->epsilon : eps; double threshold = eps * s(0); - int cut = + auto cut = std::count_if(s.data(), s.data() + s.size(), [threshold](double val) { return val >= threshold; }); if (max_size > 0) { - cut = std::min(cut, max_size); + cut = std::min(cut, static_cast(max_size)); } std::vector u_part_(u->begin(), u->begin() + cut); PiecewiseLegendrePolyVector u_part(u_part_);