Make a Grid Downward-Closed#

import minterpy as mp
import numpy as np
import matplotlib.pyplot as plt

A Grid instance is defined by a multi-index set which itself may or may not be downward-closed (see Make a Multi-Index Set Downward-Closed for more details) A Grid is therefore downward-closed if the underlying multi-index set is downward-closed; it is non-downward-closed otherwise. This guide shows how to check if a given Grid instance is downward-closed and make it downward-closed.

Note

While an interpolating grid may be defined with a non-downward-closed multi-index set, the notion of unisolvence as well as the transformation between interpolating polynomials require that the underlying multi-index set to be downward-closed.

Motivating example#

Consider a two-dimensional Leja-ordered Chebyshev-Lobatto interpolation grid whose underlying multi-index set contains the elements:

\[ A = \{ (1, 0), (1, 2) \} \]

with respect to \(l_p\)-degree of \(2.0\). This set is not downward-closed because it contains lexicographical “holes” between \((0, 0)\) and the lexicographically largest element \((1,2)\) (e.g., \((0, 0)\) itself, \((0, 1)\)).

This grid is non-downward-closed; make the grid downward-closed and plot the corresponding unisolvent nodes.

The multi-index set of the Gridcan be created in Minterpy as follows:

mi = mp.MultiIndexSet(np.array([[1, 0], [1, 2]]), lp_degree=2.0)
print(mi)
MultiIndexSet(m=2, n=3, p=2.0)
[[1 0]
 [1 2]]

An instance of Grid given the multi-index set can then be created as follows:

grd = mp.Grid(mi)

Note that by default, the underlying generating points are the Leja-ordered Chebyshev-Lobatto points.

Check for downward-closedness#

The property is_downward_closed of a Grid instance returns True if the set of exponents in the instance is downward-closed and False otherwise.

grd.is_downward_closed
False

Make downward-closed#

The method make_downward_closed() creates a complete Grid whose underlying multi-index set is downward-closed. Calling the method returns a new instance of Grid and the result can be stored in a variable for further use:

The method make_complete() creates a complete multi-index set from a given instance of MultiIndexSet.

grd_downward_closed = grd.make_downward_closed()

Notice that the Grid instance is now downward-closed:

grd_downward_closed.is_downward_closed
True

The unisolvent nodes of incomplete and complete grids are shown below:

fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].scatter(grd.unisolvent_nodes[:, 0], grd.unisolvent_nodes[:, 1])
axs[1].scatter(
    grd_downward_closed.unisolvent_nodes[:, 0],
    grd_downward_closed.unisolvent_nodes[:, 1],
);
../../_images/0dc06482edbe1c9d0ca7fb0d8af6a2f55dbe3a70858178b878eb7c7e4074366b.png

Note that, strictly speaking, the nodes shown on the left plot is not unisolvence. The nodes cannot be used to uniquely determined a polynomial defined by the multi-index set (which is non-downward-closed).