Skip to content

Commit

Permalink
Merge pull request #81 from jrenaud90/fix-bad-array-returns
Browse files Browse the repository at this point in the history
Fix bad array returns
  • Loading branch information
jrenaud90 authored Dec 2, 2024
2 parents b6f2ff2 + 938fe4a commit 70051f5
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 44 deletions.
58 changes: 29 additions & 29 deletions .github/workflows/push_tests_ubun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,33 @@ jobs:
- name: Run pytest
run: pytest -n auto -v Tests/

test-39-with-coverage:
name: Test Python 3.9 and Upload Coverage Report
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.9
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-cov cython pytest-xdist
- name: Install package
run: |
python -m pip install . -v
# test-39-with-coverage:
# name: Test Python 3.9 and Upload Coverage Report
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Set up Python 3.9
# uses: actions/setup-python@v5
# with:
# python-version: 3.9
# - name: Install Dependencies
# run: |
# python -m pip install --upgrade pip
# python -m pip install pytest pytest-cov cython pytest-xdist
# - name: Install package
# run: |
# python -m pip install . -v

- name: Run pytest
run: pytest -n auto --capture=sys -v --cov=CyRK Tests/
env:
# Disable numba so that njited functions can have their coverage checked.
NUMBA_DISABLE_JIT: 1
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
env_vars: OS,PYTHON
fail_ci_if_error: false
flags: unittests
verbose: true
name: coverage
# - name: Run pytest
# run: pytest -n auto --capture=sys -v --cov=CyRK Tests/
# env:
# # Disable numba so that njited functions can have their coverage checked.
# NUMBA_DISABLE_JIT: 1
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v3
# with:
# env_vars: OS,PYTHON
# fail_ci_if_error: false
# flags: unittests
# verbose: true
# name: coverage
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## 2024

#### v0.12.1 (2024-12-02)

Fixes:
* Added fix so that arrays returned by `WrapCySolverResult` class are not destroyed when class is. Instead they are managed by python's garbage collector once they are held by a python variable. This addresses Github issues [#80](https://github.com/jrenaud90/CyRK/issues/80) and [#78](https://github.com/jrenaud90/CyRK/issues/78)

Tests:
* Added test to check that arrays stay alive after underlying `WrapCySolverResult` class is destroyed.

#### v0.12.0 (2024-12-02)

New & Changes:
Expand Down
8 changes: 4 additions & 4 deletions CyRK/cy/cysolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ CySolverBase::CySolverBase(
const double* t_eval,
const size_t len_t_eval,
PreEvalFunc pre_eval_func) :
t_start(t_start),
t_end(t_end),
diffeq_ptr(diffeq_ptr),
size_of_args(size_of_args),
len_t_eval(len_t_eval),
num_extra(num_extra),
use_dense_output(use_dense_output),
pre_eval_func(pre_eval_func),
status(0),
num_y(num_y),
storage_sptr(storage_sptr)
num_extra(num_extra),
storage_sptr(storage_sptr),
t_start(t_start),
t_end(t_end)
{
// Parse inputs
this->capture_extra = num_extra > 0;
Expand Down
12 changes: 6 additions & 6 deletions CyRK/cy/cysolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class CySolverBase {


public:
// Differential equation information
DiffeqFuncType diffeq_ptr = nullptr;

// Integration step information
size_t max_num_steps = 0;

Expand All @@ -111,9 +114,6 @@ class CySolverBase {
std::vector<char> args_char_vec = std::vector<char>();
char* args_ptr = nullptr;

// Differential equation information
DiffeqFuncType diffeq_ptr = nullptr;

// t_eval information
std::vector<double> t_eval_vec = std::vector<double>();
double* t_eval_ptr = t_eval_vec.data();
Expand All @@ -122,9 +122,6 @@ class CySolverBase {
bool skip_t_eval = false;
bool use_t_eval = false;

// Function to send to diffeq which is called before dy is calculated
PreEvalFunc pre_eval_func = nullptr;

// Keep bools together to reduce size
bool direction_flag = false;
bool reset_called = false;
Expand All @@ -134,6 +131,9 @@ class CySolverBase {

// Dense (Interpolation) Attributes
bool use_dense_output = false;

// Function to send to diffeq which is called before dy is calculated
PreEvalFunc pre_eval_func = nullptr;

// PySolver Attributes
bool use_pysolver = false;
Expand Down
4 changes: 2 additions & 2 deletions CyRK/cy/cysolver_api.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,11 @@ cdef class WrapCySolverResult:

@property
def t(self):
return np.asarray(self.time_view, dtype=np.float64, order='C')
return np.copy(np.asarray(self.time_view, dtype=np.float64, order='C'))

@property
def y(self):
return np.asarray(self.y_view, dtype=np.float64, order='C').reshape((self.size, self.num_dy)).T
return np.copy(np.asarray(self.y_view, dtype=np.float64, order='C')).reshape((self.size, self.num_dy)).T

@property
def size(self):
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div style="text-align: center;">
<a href="https://doi.org/10.5281/zenodo.7093266"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.7093266.svg" alt="DOI"></a>
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/Python-3.8|3.9|3.10|3.11|3.12-blue" alt="Python Version 3.8-3.12" /></a>
<a href="https://codecov.io/gh/jrenaud90/CyRK" ><img src="https://codecov.io/gh/jrenaud90/CyRK/branch/main/graph/badge.svg?token=MK2PqcNGET" alt="Code Coverage"/></a>
<!-- <a href="https://codecov.io/gh/jrenaud90/CyRK" ><img src="https://codecov.io/gh/jrenaud90/CyRK/branch/main/graph/badge.svg?token=MK2PqcNGET" alt="Code Coverage"/></a> -->
<br />
<a href="https://github.com/jrenaud90/CyRK/actions/workflows/push_tests_win.yml"><img src="https://github.com/jrenaud90/CyRK/actions/workflows/push_tests_win.yml/badge.svg?branch=main" alt="Windows Tests" /></a>
<a href="https://github.com/jrenaud90/CyRK/actions/workflows/push_tests_mac.yml"><img src="https://github.com/jrenaud90/CyRK/actions/workflows/push_tests_mac.yml/badge.svg?branch=main" alt="MacOS Tests" /></a>
Expand All @@ -11,7 +11,7 @@

---

<a href="https://github.com/jrenaud90/CyRK/releases"><img src="https://img.shields.io/badge/CyRK-0.12.0 Alpha-orange" alt="CyRK Version 0.12.0 Alpha" /></a>
<a href="https://github.com/jrenaud90/CyRK/releases"><img src="https://img.shields.io/badge/CyRK-0.12.1 Alpha-orange" alt="CyRK Version 0.12.1 Alpha" /></a>


**Runge-Kutta ODE Integrator Implemented in Cython and Numba**
Expand Down
45 changes: 45 additions & 0 deletions Tests/D_PySolver_Tests/test_d_pysolve_array_lifetime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import numpy as np
from CyRK import pysolve_ivp
import gc


def diffeq(dy, t, y):
dy[0] = (1. - 0.01 * y[1]) * y[0]
dy[1] = (0.02 * y[0] - 1.) * y[1]

initial_conds = np.asarray((20., 20.), dtype=np.float64, order='C')
time_span = (0., 10.)
time_span_large = (0., 1000.)
rtol = 1.0e-4
atol = 1.0e-7

def run_diffeq_array_return():
result = pysolve_ivp(diffeq, time_span, initial_conds, method="RK45", rtol=rtol, atol=atol, pass_dy_as_arg=True)

t = result.t
y = result.y
del result
gc.collect()
return t, y

def run_diffeq_result_return():
result = pysolve_ivp(diffeq, time_span, initial_conds, method="RK45", rtol=rtol, atol=atol, pass_dy_as_arg=True)
return result

def test_pysolve_array_lifetimes():
""" Tests that the underlying arrays returned by the WrapCySolverResult class can outlive the class instance. """

# Run in a loop because sometimes memory corruptions can take a while to appear
for i in range(50):
# Get result from the result instance class
result = run_diffeq_result_return()

# Get arrays from the array return
t, y = run_diffeq_array_return()

# Check that they contain the same data
assert result.y.size == y.size
assert result.t.size == t.size

assert np.allclose(result.y, y)
assert np.allclose(result.t, t)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name='CyRK'
version = '0.12.0'
version = '0.12.1'
description='Runge-Kutta ODE Integrator Implemented in Cython and Numba.'
authors= [
{name = 'Joe P. Renaud', email = 'joe.p.renaud@gmail.com'}
Expand Down

0 comments on commit 70051f5

Please sign in to comment.