Skip to content

Libraries

Contains the library classes that store the parameters u_t, theta

Library1D

__init__(self, poly_order, diff_order) special

Calculates the temporal derivative a library/feature matrix consisting of 1) polynomials up to order poly_order, i.e. u, u^2... 2) derivatives up to order diff_order, i.e. u_x, u_xx 3) cross terms of 1) and 2), i.e. uu_x, u^2u_xx

Order of terms is derivative first, i.e. [1, u_x, u, uu_x, u^2, ...]

Only works for 1D+1 data. Also works for multiple outputs but in that case doesn't calculate polynomial and derivative cross terms.

Parameters:

Name Type Description Default
poly_order int

maximum order of the polynomial in the library

required
diff_order int

maximum order of the differentials in the library

required
Source code in deepymod/model/library.py
def __init__(self, poly_order: int, diff_order: int) -> None:
    """ Calculates the temporal derivative a library/feature matrix consisting of
    1) polynomials up to order poly_order, i.e. u, u^2...
    2) derivatives up to order diff_order, i.e. u_x, u_xx
    3) cross terms of 1) and 2), i.e. $uu_x$, $u^2u_xx$

    Order of terms is derivative first, i.e. [$1, u_x, u, uu_x, u^2, ...$]

    Only works for 1D+1 data. Also works for multiple outputs but in that case doesn't calculate
    polynomial and derivative cross terms.

    Args:
        poly_order (int): maximum order of the polynomial in the library
        diff_order (int): maximum order of the differentials in the library
        """

    super().__init__()
    self.poly_order = poly_order
    self.diff_order = diff_order

library(self, input)

Compute the temporal derivative and library for the given prediction at locations given by data. Data should have t in first column, x in second.

Parameters:

Name Type Description Default
input Tuple[torch.Tensor, torch.Tensor]

A prediction u (n_samples, n_outputs) and spatiotemporal locations (n_samples, 2).

required

Returns:

Type Description
Tuple[TensorList, TensorList]

Tuple[TensorList, TensorList]: The time derivatives [(n_samples, 1) x n_outputs] and the thetas [(n_samples, (poly_order + 1)(deriv_order + 1))] computed from the library and data.

Source code in deepymod/model/library.py
def library(self, input: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[TensorList, TensorList]:
    """ Compute the temporal derivative and library for the given prediction at locations given by data.
        Data should have t in first column, x in second.

    Args:
        input (Tuple[torch.Tensor, torch.Tensor]): A prediction u (n_samples, n_outputs) and spatiotemporal locations (n_samples, 2).

    Returns:
        Tuple[TensorList, TensorList]: The time derivatives [(n_samples, 1) x n_outputs] and the thetas [(n_samples, (poly_order + 1)(deriv_order + 1))]
        computed from the library and data.
    """
    prediction, data = input
    poly_list = []
    deriv_list = []
    time_deriv_list = []

    # Creating lists for all outputs
    for output in np.arange(prediction.shape[1]):
        time_deriv, du = library_deriv(data, prediction[:, output:output+1], self.diff_order)
        u = library_poly(prediction[:, output:output+1], self.poly_order)

        poly_list.append(u)
        deriv_list.append(du)
        time_deriv_list.append(time_deriv)

    samples = time_deriv_list[0].shape[0]
    total_terms = poly_list[0].shape[1] * deriv_list[0].shape[1]

    # Calculating theta
    if len(poly_list) == 1:
        # If we have a single output, we simply calculate and flatten matrix product
        # between polynomials and derivatives to get library
        theta = torch.matmul(poly_list[0][:, :, None], deriv_list[0][:, None, :]).view(samples, total_terms)
    else:
        theta_uv = reduce((lambda x, y: (x[:, :, None] @ y[:, None, :]).view(samples, -1)), poly_list)
        # calculate all unique combinations of derivatives
        theta_dudv = torch.cat([torch.matmul(du[:, :, None], dv[:, None, :]).view(samples, -1)[:, 1:]
                                for du, dv in combinations(deriv_list, 2)], 1)
        theta = torch.cat([theta_uv, theta_dudv], dim=1)

    return time_deriv_list, [theta]

Library2D

__init__(self, poly_order) special

Create a 2D library up to given polynomial order with second order derivatives i.e. for poly_order=1: [1, u_x, u_y, u_{xx}, u_{yy}, u_{xy}]

Parameters:

Name Type Description Default
poly_order int

maximum order of the polynomial in the library

required
Source code in deepymod/model/library.py
def __init__(self, poly_order: int) -> None:
    """ Create a 2D library up to given polynomial order with second order derivatives
     i.e. for poly_order=1: [$1, u_x, u_y, u_{xx}, u_{yy}, u_{xy}$]
    Args:
        poly_order (int): maximum order of the polynomial in the library
        """
    super().__init__()
    self.poly_order = poly_order

library(self, input)

Compute the library for the given a prediction and data

Parameters:

Name Type Description Default
input Tuple[torch.Tensor, torch.Tensor]

A prediction and its data

required

Returns:

Type Description
Tuple[TensorList, TensorList]

Tuple[TensorList, TensorList]: The time derivatives and the thetas computed from the library and data.

Source code in deepymod/model/library.py
def library(self, input: Tuple[torch.Tensor, torch.Tensor]) -> Tuple[TensorList, TensorList]:
    """ Compute the library for the given a prediction and data

    Args:
        input (Tuple[torch.Tensor, torch.Tensor]): A prediction and its data

    Returns:
        Tuple[TensorList, TensorList]: The time derivatives and the thetas
        computed from the library and data.
    """

    prediction, data = input
    # Polynomial

    u = torch.ones_like(prediction)
    for order in np.arange(1, self.poly_order+1):
        u = torch.cat((u, u[:, order-1:order] * prediction), dim=1)

    # Gradients
    du = grad(prediction, data, grad_outputs=torch.ones_like(prediction), create_graph=True)[0]
    u_t = du[:, 0:1]
    u_x = du[:, 1:2]
    u_y = du[:, 2:3]
    du2 = grad(u_x, data, grad_outputs=torch.ones_like(prediction), create_graph=True)[0]
    u_xx = du2[:, 1:2]
    u_xy = du2[:, 2:3]
    u_yy = grad(u_y, data, grad_outputs=torch.ones_like(prediction), create_graph=True)[0][:, 2:3]

    du = torch.cat((torch.ones_like(u_x), u_x, u_y, u_xx, u_yy, u_xy), dim=1)

    samples = du.shape[0]
    # Bringing it together
    theta = torch.matmul(u[:, :, None], du[:, None, :]).view(samples, -1)

    return [u_t], [theta]

library_deriv(data, prediction, max_order)

Given a prediction u evaluated at data (t, x), returns du/dt and du/dx up to max_order, including ones as first column.

Parameters:

Name Type Description Default
data Tensor

(t, x) locations of where to evaluate derivatives (n_samples x 2)

required
prediction Tensor

the data u for which to evaluate the library (n_samples x 1)

required
max_order int

maximum order of derivatives to be calculated.

required

Returns:

Type Description
Tuple[torch.Tensor, torch.Tensor]

Tuple[torch.Tensor, torch.Tensor]: time derivative and feature library ((n_samples, 1), (n_samples, max_order + 1))

Source code in deepymod/model/library.py
def library_deriv(data: torch.Tensor, prediction: torch.Tensor, max_order: int) -> Tuple[torch.Tensor, torch.Tensor]:
    """Given a prediction u evaluated at data (t, x), returns du/dt and du/dx up to max_order, including ones
    as first column.

    Args:
        data (torch.Tensor): (t, x) locations of where to evaluate derivatives (n_samples x 2)
        prediction (torch.Tensor): the data u for which to evaluate the library (n_samples x 1)
        max_order (int): maximum order of derivatives to be calculated.

    Returns:
        Tuple[torch.Tensor, torch.Tensor]: time derivative and feature library ((n_samples, 1), (n_samples,  max_order + 1))
    """
    dy = grad(prediction, data, grad_outputs=torch.ones_like(prediction), create_graph=True)[0]
    time_deriv = dy[:, 0:1]

    if max_order == 0:
        du = torch.ones_like(time_deriv)
    else:
        du = torch.cat((torch.ones_like(time_deriv), dy[:, 1:2]), dim=1)
        if max_order > 1:
            for order in np.arange(1, max_order):
                du = torch.cat((du, grad(du[:, order:order+1], data,
                                grad_outputs=torch.ones_like(prediction), create_graph=True)[0][:, 1:2]), dim=1)

    return time_deriv, du

library_poly(prediction, max_order)

Given a prediction u, returns u^n up to max_order, including ones as first column.

Parameters:

Name Type Description Default
prediction Tensor

the data u for which to evaluate the library (n_samples x 1)

required
max_order int

the maximum polynomial order up to which compute the library

required

Returns:

Type Description
Tensor

torch.Tensor: Tensor with polynomials (n_samples, max_order + 1)

Source code in deepymod/model/library.py
def library_poly(prediction: torch.Tensor, max_order: int) -> torch.Tensor:
    """Given a prediction u, returns u^n up to max_order, including ones as first column.

    Args:
        prediction (torch.Tensor): the data u for which to evaluate the library (n_samples x 1)
        max_order (int): the maximum polynomial order up to which compute the library

    Returns:
        torch.Tensor: Tensor with polynomials (n_samples, max_order + 1)
    """
    u = torch.ones_like(prediction)
    for order in np.arange(1, max_order+1):
        u = torch.cat((u, u[:, order-1:order] * prediction), dim=1)

    return u