Note
Go to the end to download the full example code.
Tabular Data¶
It is often useful to interpolate pre-existing data. For this, the
TableLookup
model provides a convenient way to specify the
interpolant input and output data. This model also provids an example of using a
ExternalSolverWrapper
by wrapping uses the ndsplines library to perform the interpolation and
compute derivatives as needed for tensor-product B-splines. Note that this table
model assumes fixed input and output data, but a model with variable input and output
data could be defined as needs arise.
Because TableLookup
is an ExternalSolverWrapper
, the declaration of
a model quite different from a standard ModelTemplate
,
with the relevant data is passed in in a way that appears more similar to a standard
Python object instantiation with arguments for the input data, output data, degree,
and boundary conditions. Condor supports any number of inputs, and automatically
computes the derivatives
Here we demonstrate the construction of a single-input, single-output table for the
import numpy as np
import condor
from condor.backend import operators as ops
# input and output data are dictionaries with keys for the name of the element and
# values to construct the interpolant.
data_x = dict(x=np.linspace(-1, 1, 5) * ops.pi)
data_y = dict(y=ops.sin(data_x["x"]))
SinTable = condor.TableLookup(data_x, data_y)
out = SinTable(np.pi / 2)
print(out.y)
assert np.isclose(out.y, 1)
[1.]
Next, we construct a table with two inputs and a single output
Table = condor.TableLookup(
dict(
x1=[-1, -0.5, 0, 0.5, 1],
x2=[0, 1, 2, 3],
),
dict(
y1=[
[0, 1, 2, 3],
[3, 4, 5, 6],
[6, 7, 8, 9],
[8, 7, 6, 5],
[4, 3, 2, 1],
]
),
)
tab_out = Table(x1=0.5, x2=0.1)
print(tab_out.output)
TablelookupOutput(y1=array([7.62482755]))
Next we demonstrate specifying the degrees (and boundary conditions) for the
SinTable
. Note that these can be specified for each input (and boundary)
independently, or a single custom value can be broadcast to each input (and boundary).
from matplotlib import pyplot as plt
eval_x = np.linspace(-1, 1, 100) * np.pi
fig, ax = plt.subplots(constrained_layout=True)
for k in [0, 1, 3]:
if k == 3:
# for cubic polynomial, use constant slope (constant first derivative, 0 second
# derivative) boundary condition instead of default not-a-knot (constant,
# non-zero, second derivative)
bcs = (2, 0)
else:
# else, use default
bcs = (-1, 0)
SinTable = condor.TableLookup(data_x, data_y, degrees=k, bcs=bcs)
y = np.array([SinTable(x).y for x in eval_x]).squeeze()
plt.plot(eval_x, y, label=f"k={k}")
plt.plot(data_x["x"], data_y["y"], "ko")
plt.plot(eval_x, np.sin(eval_x), "k--", label="true")
plt.grid(True)
plt.legend()
plt.show()

Total running time of the script: (0 minutes 0.426 seconds)