Skip to content

Commit b62dd51

Browse files
committed
Tests and issue #90
1 parent 53f3134 commit b62dd51

File tree

7 files changed

+75
-32
lines changed

7 files changed

+75
-32
lines changed

findiff/findiff.py

+13
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ def __init__(self, axis, order, spacing, acc):
8888

8989
def __call__(self, f):
9090
self.validate_f(f)
91+
if np.issubdtype(f.dtype, np.integer):
92+
f = f.astype(np.float64)
93+
9194
npts = f.shape[self.axis]
9295
fd = np.zeros_like(f)
9396
num_bndry_points = len(self.center["coefficients"]) // 2
@@ -177,6 +180,12 @@ def __init__(self, axis, order, spacing, acc):
177180

178181
def __call__(self, f):
179182
self.validate_f(f)
183+
if np.issubdtype(f.dtype, np.integer):
184+
f = f.astype(np.float64)
185+
186+
if np.issubdtype(f.dtype, np.integer):
187+
f = f.astype(np.float64)
188+
180189
fd = np.zeros_like(f)
181190
for off, coef in zip(self.coefs["offsets"], self.coefs["coefficients"]):
182191
fd += coef * np.roll(f, -off, axis=self.axis)
@@ -212,7 +221,11 @@ def __init__(self, axis, order, coords, acc):
212221
def __call__(self, y):
213222
"""The core function to take a partial derivative on a non-uniform grid"""
214223

224+
if np.issubdtype(y.dtype, np.integer):
225+
y = y.astype(np.float64)
226+
215227
order, dim = self.order, self.axis
228+
216229
yd = np.zeros_like(y)
217230

218231
ndims = len(y.shape)

pyproject.toml

+20-6
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ build-backend = "setuptools.build_meta"
55
[project]
66
name = "findiff"
77
authors = [
8-
{name = "Matthias Baer"},
8+
{ name = "Matthias Baer" },
99
]
1010
maintainers = [
11-
{name = "Matthias Baer", email="[email protected]"},
11+
{ name = "Matthias Baer", email = "[email protected]" },
1212
]
1313
description = "A Python package for finite difference derivatives in any number of dimensions."
1414
readme = "README.md"
15-
license = {text = "MIT"}
15+
license = { text = "MIT" }
1616
dependencies = [
1717
"numpy",
1818
"scipy",
@@ -47,6 +47,20 @@ include = ["findiff"]
4747
[tool.setuptools.dynamic]
4848
version = { attr = "findiff.__version__" }
4949

50+
[tool.pytest.ini_options]
51+
addopts = [
52+
"--strict-markers"
53+
]
54+
testpaths = "tests"
55+
markers = [
56+
"functional: Functional tests for stuff that the user would do",
57+
"one_dimensional: Tests in 1D",
58+
"periodic: Tests for periodic boundary conditions",
59+
"invalid_args: Tests for invalid argument handling",
60+
"default_args: Tests for default argument handling",
61+
"grid_spec: Marker to construct grid data by fixtures"
62+
]
63+
5064
[tool.coverage]
5165
run.source_pkgs = ["findiff", "tests"]
5266
run.branch = true
@@ -96,9 +110,9 @@ commands = [
96110
[tool.ruff]
97111
line-length = 88
98112
lint.extend-select = [
99-
"B", # flake8-bugbear
100-
"I", # isort
101-
"UP", # pyupgrade
113+
"B", # flake8-bugbear
114+
"I", # isort
115+
"UP", # pyupgrade
102116
]
103117
extend-exclude = [
104118
"docs/source/**/*.ipynb",

pytest.ini

-9
This file was deleted.

tests/conftest.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@ def grid_data(request):
99
raise ValueError("Grid data marker not defined")
1010
shape = m.kwargs["shape"]
1111
edges = m.kwargs["edges"]
12+
endpoints = m.kwargs.get("endpoints", [True] * len(shape))
1213

1314
if len(shape) == 1:
14-
x = np.linspace(*edges, shape[0])
15+
x = np.linspace(*edges, shape[0], endpoint=endpoints[0])
1516
dx = x[1] - x[0]
1617
return x, dx
1718

1819
axes = tuple(
19-
[np.linspace(edges[k][0], edges[k][1], shape[k]) for k in range(len(shape))]
20+
[
21+
np.linspace(edges[k][0], edges[k][1], shape[k], endpoint=endpoints[k])
22+
for k in range(len(shape))
23+
]
2024
)
2125
coords = np.meshgrid(*axes, indexing="ij")
2226
spacings = [axes[k][1] - axes[k][0] for k in range(len(shape))]

tests/test_bugs.py

+21
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import numpy as np
22
import pytest
3+
from numpy.testing import assert_array_almost_equal
34

45
import findiff
56
from findiff import FinDiff
7+
from findiff.coefs import coefficients_non_uni
68

79

810
def test_findiff_should_raise_exception_when_applied_to_unevaluated_function():
@@ -141,3 +143,22 @@ def assert_dict_almost_equal(first, second):
141143
assert first[k] == pytest.approx(0, abs=1.0e-8)
142144
for k in set(second) - set(first):
143145
assert 0 == pytest.approx(second[k], abs=1.0e-8)
146+
147+
148+
class TestIssue90:
149+
150+
def test_reproduce_issue90(self):
151+
152+
x = np.array([0.0, 1.0, 1.5, 3.5, 4.0, 6.0])
153+
f1 = np.array([1, 2, 4, 7, 11, 16])
154+
f2 = np.sin(x)
155+
156+
d_dx = FinDiff(0, x, acc=2)
157+
df_dx1 = d_dx(f1)
158+
df_dx2 = d_dx(f2)
159+
160+
grad1 = np.gradient(f1, x, edge_order=2)
161+
grad2 = np.gradient(f2, x, edge_order=2)
162+
163+
assert_array_almost_equal(df_dx2, grad2)
164+
assert_array_almost_equal(df_dx1, grad1)

tests/test_diff.py

-10
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,6 @@
77
from findiff import Diff, Identity
88

99

10-
def test_partial_d_dx_periodic():
11-
x = np.linspace(0, 2 * np.pi, 200, endpoint=False)
12-
dx = x[1] - x[0]
13-
f = np.sin(x)
14-
expected = np.cos(x)
15-
actual = Diff(0, dx, periodic=True, acc=4)(f)
16-
17-
assert_array_almost_equal(expected, actual)
18-
19-
2010
def test_partial_d2_dx2_matrix_periodic():
2111
dx = 1
2212
expected = np.array(

tests/test_functional.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class TestDiff_1D:
1212

1313
@pytest.mark.grid_spec(shape=(101,), edges=(0, 1))
14-
def test_diff_1d(self, grid_data):
14+
def test_diff(self, grid_data):
1515
x, dx = grid_data
1616

1717
u = x**2
@@ -23,7 +23,7 @@ def test_diff_1d(self, grid_data):
2323
assert_array_almost_equal(expected, actual)
2424

2525
@pytest.mark.grid_spec(shape=(101,), edges=(0, 1))
26-
def test_diff_1d_deferred(self, grid_data):
26+
def test_diff_deferred(self, grid_data):
2727
x, dx = grid_data
2828

2929
u = x**2
@@ -35,15 +35,15 @@ def test_diff_1d_deferred(self, grid_data):
3535

3636
assert_array_almost_equal(expected, actual)
3737

38-
def test_diff_1d_deferred_called_too_early(self):
38+
def test_diff_deferred_called_too_early(self):
3939
u = np.zeros(10)
4040
fd = Diff(0)
4141
with pytest.raises(TypeError, match="Unknown axis type."):
4242
fd(u)
4343

4444
@pytest.mark.default_args
4545
@pytest.mark.grid_spec(shape=(101,), edges=(0, 1))
46-
def test_diff_1d_defaults(self, grid_data):
46+
def test_diff_defaults(self, grid_data):
4747
x, dx = grid_data
4848

4949
u = x**2
@@ -56,10 +56,20 @@ def test_diff_1d_defaults(self, grid_data):
5656
assert_array_almost_equal(expected, actual)
5757

5858
@pytest.mark.invalid_args
59-
def test_diff_1d_invalid_args(self):
59+
def test_diff_invalid_args(self):
6060

6161
with pytest.raises(ValueError, match="Dimension must be >= 0"):
6262
Diff(-1, 1)
6363

6464
with pytest.raises(ValueError, match="Spacing must be > 0."):
6565
Diff(0, -1)
66+
67+
@pytest.mark.periodic
68+
@pytest.mark.grid_spec(shape=[200], edges=(0, 2 * np.pi), endpoints=[False])
69+
def test_diff_periodic(self, grid_data):
70+
x, dx = grid_data
71+
f = np.sin(x)
72+
73+
actual = Diff(0, dx, periodic=True, acc=4)(f)
74+
75+
assert_array_almost_equal(np.cos(x), actual)

0 commit comments

Comments
 (0)