Repository: jrenaud90/CyRK (language: python)

Issue:
Fixes

There is something wrong with the CyRK==0.10.1 wheel for py310 on win_amd64 from PyPI
If you try to install the `CyRK-0.10.1-cp310-cp310-win_amd64.whl` wheel from PyPI (using pip) you get the following error:

```shell
ERROR: Exception:
Traceback (most recent call last):
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\cli\base_command.py", line 105, in _run_wrapper
    status = _inner_run()
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\cli\base_command.py", line 96, in _inner_run
    return self.run(options, args)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\cli\req_command.py", line 67, in wrapper
    return func(self, options, args)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\commands\install.py", line 457, in run
    installed = install_given_reqs(
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\req\__init__.py", line 70, in install_given_reqs
    requirement.install(
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\req\req_install.py", line 867, in install
    install_wheel(
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\operations\install\wheel.py", line 732, in install_wheel
    _install_wheel(
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\operations\install\wheel.py", line 590, in _install_wheel
    file.save()
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\site-packages\pip\_internal\operations\install\wheel.py", line 380, in save
    shutil.copyfileobj(f, dest, blocksize)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\shutil.py", line 195, in copyfileobj
    buf = fsrc_read(length)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\zipfile.py", line 930, in read
    data = self._read1(n)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\zipfile.py", line 1020, in _read1
    self._update_crc(data)
  File "C:\Users\naqsL\miniconda3\envs\py310\lib\zipfile.py", line 948, in _update_crc
    raise BadZipFile("Bad CRC-32 for file %r" % self.name)
zipfile.BadZipFile: Bad CRC-32 for file 'CyRK/array/interp.cp310-win_amd64.pyd'
```

It appears there is some checksum-like issue with the compression in the wheel.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/build_wheels_main_pypi.yml b/.github/workflows/build_wheels_main_pypi.yml
index 5cb9fa1..8eaaa83 100644
--- a/.github/workflows/build_wheels_main_pypi.yml
+++ b/.github/workflows/build_wheels_main_pypi.yml
@@ -41,7 +41,7 @@ jobs:
         uses: actions/checkout@v4
 
       - name: Install Anaconda
-        uses: conda-incubator/setup-miniconda@v3
+        uses: conda-incubator/setup-miniconda@main
         with:
           activate-environment: cyrk_macos_latest_wheels
           auto-update-conda: true
@@ -51,15 +51,22 @@ jobs:
       - name: Conda info
         shell: bash -el {0}
         run: conda info
+      
+      - name: install llvm # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
+        shell: bash -el {0}
+        run: |
+          brew install llvm libomp
 
       - name: Install package
         shell: bash -el {0}
         run: |
-          conda install pytest matplotlib numba numpy scipy cython
-          python -m pip install --upgrade build
-          export CC=gcc
-          export CXX=gcc
-          export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
+          conda install pytest matplotlib numba numpy scipy cython pytest-xdist
+          export LDFLAGS="-L/opt/homebrew/opt/llvm/lib"
+          export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"
+          export LDFLAGS="-L/opt/homebrew/opt/libomp/lib"
+          export CPPFLAGS="-I/opt/homebrew/opt/libomp/include"
+          export CC=/opt/homebrew/opt/llvm/bin/clang
+          export CXX=/opt/homebrew/opt/llvm/bin/clang++
           python -m build --wheel --outdir ./wheelhouse/
 
       - uses: actions/upload-artifact@v4
@@ -96,20 +103,22 @@ jobs:
         shell: bash -el {0}
         run: conda info
 
-      - name: install gcc-13  # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
+      - name: install llvm # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
         shell: bash -el {0}
         run: |
-          brew install gcc@13
+          brew install llvm libomp
 
       - name: Install package
         shell: bash -el {0}
         run: |
           conda install nomkl
-          conda install pytest matplotlib numba numpy scipy cython
-          python -m pip install --upgrade build
-          export CC=gcc
-          export CXX=gcc
-          export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
+          conda install pytest matplotlib numba numpy scipy cython pytest-xdist
+          export LDFLAGS="-L/usr/local/opt/llvm/lib"
+          export CPPFLAGS="-I/usr/local/opt/llvm/include"
+          export LDFLAGS="-L/usr/local/opt/libomp/lib"
+          export CPPFLAGS="-I/usr/local/opt/libomp/include"
+          export CC=/usr/local/opt/llvm/bin/clang
+          export CXX=/usr/local/opt/llvm/bin/clang++
           python -m build --wheel --outdir ./wheelhouse/
 
       - uses: actions/upload-artifact@v4
@@ -135,7 +144,7 @@ jobs:
           fetch-depth: 0
 
       - name: Build wheels
-        uses: pypa/cibuildwheel@v2.19.2
+        uses: pypa/cibuildwheel@main
 
       - uses: actions/upload-artifact@v4
         with:
@@ -164,7 +173,7 @@ jobs:
           merge-multiple: true
           path: dist
 
-      - uses: pypa/gh-action-pypi-publish@v1.9.0
+      - uses: pypa/gh-action-pypi-publish@release/v1
         with:
           user: __token__
           password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/CHANGES.md b/CHANGES.md
index cc5f4f7..546daa2 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -2,6 +2,20 @@
 
 ## 2024
 
+#### v0.10.2 (2024-11-05)
+
+New:
+* Added new `interpolate_from_solution_list` function to help interpolate between multiple solutions across a domain.
+
+Bugs:
+* Fixed issue where `CyRK.test_cysolver()` used incorrect kind and order of arguments.
+* Fixed MacOS compile issues when using OpenMP (for both x86-64 and arm64 macos).
+* Fixed issue where MacOS was failing certain tests.
+* Building new wheels to fix Github issue [#62](https://github.com/jrenaud90/CyRK/issues/62).
+
+Tests:
+* Added tests to check all built in testers.
+
 #### v0.10.1 (2024-07-25)
 
 C++ Backend:
diff --git a/CyRK/__init__.pxd b/CyRK/__init__.pxd
index fdf80a7..93b590a 100644
--- a/CyRK/__init__.pxd
+++ b/CyRK/__init__.pxd
@@ -1,1 +1,2 @@
-from CyRK.cy.cysolverNew cimport cysolve_ivp, cysolve_ivp_gil, DiffeqFuncType, PreEvalFunc, CySolverResult, WrapCySolverResult, CySolverBase, CySolveOutput, RK23_METHOD_INT, RK45_METHOD_INT, DOP853_METHOD_INT
\ No newline at end of file
+from CyRK.cy.cysolverNew cimport cysolve_ivp, cysolve_ivp_gil, DiffeqFuncType, PreEvalFunc, CySolverResult, WrapCySolverResult, CySolverBase, CySolveOutput, RK23_METHOD_INT, RK45_METHOD_INT, DOP853_METHOD_INT
+from CyRK.cy.helpers cimport interpolate_from_solution_list
\ No newline at end of file
diff --git a/CyRK/cy/helpers.pxd b/CyRK/cy/helpers.pxd
new file mode 100644
index 0000000..0c47462
--- /dev/null
+++ b/CyRK/cy/helpers.pxd
@@ -0,0 +1,11 @@
+from CyRK.utils.vector cimport vector
+from CyRK.cy.cysolverNew cimport CySolveOutput, CySolverResult
+
+cdef void interpolate_from_solution_list(
+    double* y_result_ptr,
+    int num_y,
+    vector[CySolveOutput] solution_list_vec,
+    int num_solutions,
+    double* x_domain_ptr,
+    size_t x_domain_size,
+    vector[double] x_breakpoints_vec) noexcept nogil
\ No newline at end of file
diff --git a/CyRK/cy/helpers.pyx b/CyRK/cy/helpers.pyx
new file mode 100644
index 0000000..a198916
--- /dev/null
+++ b/CyRK/cy/helpers.pyx
@@ -0,0 +1,34 @@
+# distutils: language = c++
+# cython: boundscheck=False, wraparound=False, nonecheck=False, cdivision=True, initializedcheck=False
+
+
+cdef void interpolate_from_solution_list(
+        double* y_result_ptr,
+        int num_y,
+        vector[CySolveOutput] solution_list_vec,
+        int num_solutions,
+        double* x_domain_ptr,
+        size_t x_domain_size,
+        vector[double] x_breakpoints_vec) noexcept nogil:
+    """ Steps through multiple cysolve solutions to interpolate using a single all-domain domain. """
+    
+    cdef int current_sol_i = 0
+    cdef double current_sol_upper_x = x_breakpoints_vec[0]
+    cdef double* y_result_subptr = y_result_ptr
+    cdef CySolverResult* cy_solution_ptr = solution_list_vec[0].get()
+
+    cdef size_t x_i
+    cdef double x
+    
+    for x_i in range(x_domain_size):
+        
+        x = x_domain_ptr[x_i]
+        if x > current_sol_upper_x:
+            # We are ready for the next solution.
+            current_sol_i += 1
+            current_sol_upper_x = x_breakpoints_vec[current_sol_i]
+            cy_solution_ptr = solution_list_vec[current_sol_i].get()
+        
+        # Run cysolver interpolator
+        y_result_subptr = &y_result_ptr[x_i * num_y]
+        cy_solution_ptr.call(x, y_result_subptr)
diff --git a/README.md b/README.md
index 83441cd..a507ab4 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
 
 ---
 
-<a href="https://github.com/jrenaud90/CyRK/releases"><img src="https://img.shields.io/badge/CyRK-0.10.1 Alpha-orange" alt="CyRK Version 0.10.1 Alpha" /></a>
+<a href="https://github.com/jrenaud90/CyRK/releases"><img src="https://img.shields.io/badge/CyRK-0.10.2 Alpha-orange" alt="CyRK Version 0.10.2 Alpha" /></a>
 
 
 **Runge-Kutta ODE Integrator Implemented in Cython and Numba**
diff --git a/_build_cyrk.py b/_build_cyrk.py
index ba6479d..bc5b5b4 100644
--- a/_build_cyrk.py
+++ b/_build_cyrk.py
@@ -20,9 +20,8 @@
     extra_link_args = []
 elif install_platform.lower() == 'darwin':
     # OpenMP is installed via llvm. See https://stackoverflow.com/questions/60005176/how-to-deal-with-clang-error-unsupported-option-fopenmp-on-travis
-    #os.environ["CXX"] = "g++"
-    extra_compile_args = ['-O3', '-Wno-error=incompatible-function-pointer-types']
-    extra_link_args = []
+    extra_compile_args = ['-O3', '-Wno-error=incompatible-function-pointer-types', '-fopenmp']
+    extra_link_args = ['-lomp']
 else:
     extra_compile_args = ['-fopenmp', '-O3']
     extra_link_args = ['-fopenmp', '-O3']
diff --git a/cython_extensions.json b/cython_extensions.json
index bef0547..edcc9b6 100644
--- a/cython_extensions.json
+++ b/cython_extensions.json
@@ -104,5 +104,13 @@
     "compile_args": [],
     "link_args": [],
     "is_cpp": false
+  },
+  "cysolver_helpers": {
+    "name": "CyRK.cy.helpers",
+    "sources": [["CyRK", "cy", "helpers.pyx"]],
+    "include_dirs": [["CyRK", "cy"]],
+    "compile_args": [],
+    "link_args": [],
+    "is_cpp": true
   }
 }
diff --git a/pyproject.toml b/pyproject.toml
index 2df5ba5..fd60638 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [project]
 name='CyRK'
-version = '0.10.1'
+version = '0.10.2'
 description='Runge-Kutta ODE Integrator Implemented in Cython and Numba.'
 authors= [
     {name = 'Joe P. Renaud', email = 'joe.p.renaud@gmail.com'}


Test patch:
diff --git a/.github/workflows/build_wheels_test_pypi.yml b/.github/workflows/build_wheels_test_pypi.yml
deleted file mode 100644
index 75f8d7d..0000000
--- a/.github/workflows/build_wheels_test_pypi.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: Build Wheels for Test PyPI
-
-on:
-  workflow_dispatch:
-
-jobs:
-  make_sdist:
-    name: Make SDist
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v4
-      with:
-        submodules: true  # Optional, use if you have submodules
-
-    - name: Build SDist
-      run: pipx run build --sdist
-
-    - uses: actions/upload-artifact@v4
-      with:
-        path: dist/*.tar.gz
-
-  build_wheels:
-    name: Build ${{ matrix.platform }} wheels
-    runs-on: ${{ matrix.platform }}
-    strategy:
-      fail-fast: false
-      matrix:
-          platform:
-              - macos-12
-              - windows-2022
-              - ubuntu-20.04
-
-    steps:
-      - uses: actions/checkout@v4
-        with:
-          fetch-depth: 0
-
-      - name: Build wheels
-        uses: pypa/cibuildwheel@v2.16.5
-
-      - uses: actions/upload-artifact@v4
-        with:
-          path: ./wheelhouse/*.whl
-
-  check_dist:
-    name: Check dist
-    needs: [make_sdist, build_wheels]
-    runs-on: ubuntu-22.04
-    steps:
-      - uses: actions/download-artifact@v4
-        with:
-          name: artifact
-          path: dist
-
-      - run: pipx run twine check --strict dist/*
-
-  upload_all:
-    name: Upload wheels to Test PyPI
-    needs: [build_wheels, make_sdist, check_dist]
-    runs-on: ubuntu-latest
-    # if: github.event_name == 'release' && github.event.action == 'published'
-    steps:
-      - uses: actions/download-artifact@v4
-        with:
-          name: artifact
-          path: dist
-
-      - uses: pypa/gh-action-pypi-publish@v1.6.4
-        with:
-          user: __token__
-          password: ${{ secrets.TESTPYPI_API_TOKEN }}
-          repository_url: https://test.pypi.org/legacy/
\ No newline at end of file
diff --git a/.github/workflows/push_tests_mac.yml b/.github/workflows/push_tests_mac.yml
index 255e649..a2b9727 100644
--- a/.github/workflows/push_tests_mac.yml
+++ b/.github/workflows/push_tests_mac.yml
@@ -35,18 +35,22 @@ jobs:
         shell: bash -el {0}
         run: conda info
         
-      - name: install gcc-13 # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
+      - name: install llvm # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
         shell: bash -el {0}
         run: |
-          brew install gcc@13
+          brew install llvm libomp
 
       - name: Install package
         shell: bash -el {0}
+        # export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
         run: |
           conda install pytest matplotlib numba numpy scipy cython pytest-xdist
-          export CC=gcc
-          export CXX=gcc
-          export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
+          export LDFLAGS="-L/opt/homebrew/opt/llvm/lib"
+          export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"
+          export LDFLAGS="-L/opt/homebrew/opt/libomp/lib"
+          export CPPFLAGS="-I/opt/homebrew/opt/libomp/include"
+          export CC=/opt/homebrew/opt/llvm/bin/clang
+          export CXX=/opt/homebrew/opt/llvm/bin/clang++
           python -m pip install -v .
         
       - name: Run pytest
@@ -80,15 +84,24 @@ jobs:
       - name: Conda info
         shell: bash -el {0}
         run: conda info
+      
+      - name: install llvm # openMP does not play nice with clang on MacOS; also some versions of macos use older gcc so there is a need to install latest.
+        shell: bash -el {0}
+        run: |
+          brew install llvm libomp
 
       - name: Install package
         shell: bash -el {0}
+        # export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
         run: |
           conda install nomkl
           conda install pytest matplotlib numba numpy scipy cython pytest-xdist
-          export CC=gcc
-          export CXX=gcc
-          export CPPFLAGS="$CPPFLAGS -Xpreprocessor -fopenmp -lgomp"
+          export LDFLAGS="-L/usr/local/opt/llvm/lib"
+          export CPPFLAGS="-I/usr/local/opt/llvm/include"
+          export LDFLAGS="-L/usr/local/opt/libomp/lib"
+          export CPPFLAGS="-I/usr/local/opt/libomp/include"
+          export CC=/usr/local/opt/llvm/bin/clang
+          export CXX=/usr/local/opt/llvm/bin/clang++
           python -m pip install -v .
         
       - name: Run pytest
diff --git a/CyRK/_test.py b/CyRK/_test.py
index 73aaece..3542eae 100644
--- a/CyRK/_test.py
+++ b/CyRK/_test.py
@@ -56,7 +56,16 @@ def test_cysolver():
 
     from CyRK.cy.cysolverNew_test import cytester
 
-    result = cytester(0, time_span, initial_conds, None, 1, 0, 0, 2000, rtol, atol)
+    result = cytester(0,
+                      time_span,
+                      initial_conds_float,
+                      args=None,
+                      method=1,
+                      expected_size=0,
+                      max_num_steps=0,
+                      max_ram_MB=2000,
+                      rtol=rtol,
+                      atol=atol)
 
     assert result.success
     assert type(result.t) == np.ndarray
diff --git a/Tests/A_Package_Tests/test_package.py b/Tests/A_Package_Tests/test_package.py
index 36b58b6..56f5d47 100644
--- a/Tests/A_Package_Tests/test_package.py
+++ b/Tests/A_Package_Tests/test_package.py
@@ -5,3 +5,27 @@ def test_package():
 
     assert type(version) == str
     assert version == __version__
+
+def test_testers_nbrk():
+
+    from CyRK import test_nbrk
+
+    test_nbrk()
+
+    assert True
+
+def test_testers_cysolver():
+
+    from CyRK import test_cysolver
+
+    test_cysolver()
+
+    assert True
+
+def test_testers_pysolver():
+
+    from CyRK import test_pysolver
+
+    test_pysolver()
+
+    assert True
diff --git a/Tests/F_CySolver_Tests/test_a_cysolve_ivp.py b/Tests/F_CySolver_Tests/test_a_cysolve_ivp.py
index b751c74..bca252b 100644
--- a/Tests/F_CySolver_Tests/test_a_cysolve_ivp.py
+++ b/Tests/F_CySolver_Tests/test_a_cysolve_ivp.py
@@ -1,10 +1,5 @@
 import numpy as np
 import pytest
-import platform
-
-on_macos = False
-if platform.system().lower() == 'darwin':
-    on_macos = True
 
 from CyRK.cy.cysolverNew import WrapCySolverResult
 from CyRK.cy.cysolverNew_test import cytester
@@ -190,13 +185,8 @@ def correct_answer(t, c1_, c2_):
 def test_cysolve_ivp_all_diffeqs(cysolve_test_func):
     """ Check all of the currently implemented test diffeqs for cysolve_ivp"""
 
-    result = \
-        cytester(cysolve_test_func)
+    result = cytester(cysolve_test_func)
     
-    # There is a weird fail state that occasionally happens on MacOS for Python 3.10 where diffeq #5 fails.
-    if not result.success and on_macos and cysolve_test_func==5:
-        pytest.skip("Weird macos bug on diffeq5")
-
     assert result.success
     assert result.t.size > 0
     assert result.y.size > 0