Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ezyrb/approximation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"KNeighborsRegressor",
"RadiusNeighborsRegressor",
"SklearnApproximation",
"CloughTocher",
]

from .approximation import Approximation
Expand All @@ -19,3 +20,4 @@
from .kneighbors_regressor import KNeighborsRegressor
from .radius_neighbors_regressor import RadiusNeighborsRegressor
from .sklearn_approximation import SklearnApproximation
from .clough_tocher import CloughTocher
52 changes: 52 additions & 0 deletions ezyrb/approximation/clough_tocher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Wrapper for Clough-Tocher 2D Interpolator."""

import logging
import numpy as np
from scipy.interpolate import CloughTocher2DInterpolator as CT

from .approximation import Approximation

logger = logging.getLogger(__name__)


class CloughTocher(Approximation):
r"""
:math:`C^1` smooth, piecewise cubic interpolator for 2D multivariate approximation.

Note: This interpolator only supports 2-dimensional parameter spaces
(i.e., mapping :math:`\mathbb{R}^2 \to \mathbb{R}^m`).

:param kwargs: arguments passed to the internal instance of
scipy.interpolate.CloughTocher2DInterpolator.
"""

def __init__(self, **kwargs):
logger.debug("Initializing CloughTocher with kwargs: %s", kwargs)
super().__init__()
self.kwargs = kwargs
self.interpolator = None

def fit(self, points, values):
"""
Construct the interpolator given `points` and `values`.
"""
as_np_array = np.array(points)

# Mathematical constraint: CT only works in R^2
if as_np_array.ndim != 2 or as_np_array.shape[1] != 2:
logger.error(
"CloughTocher requested for data with shape %s",
as_np_array.shape,
)
raise ValueError(
"CloughTocher interpolator only supports exactly 2D parameter spaces."
)

self.interpolator = CT(as_np_array, values, **self.kwargs)
logger.info("CloughTocher fitted successfully")

def predict(self, new_point):
"""
Evaluate interpolator at given `new_points`.
"""
return self.interpolator(new_point).squeeze()
41 changes: 41 additions & 0 deletions tests/test_clough_tocher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import numpy as np
import pytest

from ezyrb import CloughTocher

np.random.seed(17)

def get_xy():
npts = 20
dinput = 2

inp = np.random.uniform(-1, 1, size=(npts, dinput))
out = np.array([
np.sin(inp[:, 0]) + np.sin(inp[:, 1]**2),
np.cos(inp[:, 0]) + np.cos(inp[:, 1]**2)
]).T

return inp, out

class TestCloughTocher:
def test_constructor_empty(self):
model = CloughTocher()

def test_fit(self):
x, y = get_xy()
approx = CloughTocher()
approx.fit(x, y)

def test_predict_01(self):
x, y = get_xy()
approx = CloughTocher()
approx.fit(x, y)
test_y = approx.predict(x)
np.testing.assert_array_almost_equal(y, test_y, decimal=6)

def test_wrong_dimensions(self):
x = np.random.uniform(-1, 1, size=(10, 3))
y = np.random.uniform(-1, 1, size=(10, 2))
approx = CloughTocher()
with pytest.raises(ValueError):
approx.fit(x, y)
7 changes: 7 additions & 0 deletions tests/test_parallel/test_clough_tocher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import pytest

import ezyrb
from ezyrb.parallel import ReducedOrderModel as ParallelROM
ezyrb.ReducedOrderModel = ParallelROM

from tests.test_clough_tocher import *
Loading