dynamicslab / pysindy

A package for the sparse identification of nonlinear dynamical systems from data
https://pysindy.readthedocs.io/en/latest/
Other
1.36k stars 304 forks source link

Total freedom in library functions with CustomLibrary #509

Open gdeplus opened 1 month ago

gdeplus commented 1 month ago

Hello,

I have tried generating library functions using CustomLibrary and PolynomialLibrary but found some difficulties when trying to get define a fine tuned library.

Fine tune the selection of function that go into the library

When constructing a model, certain symmetries and physical considerations heavily restrict the shape of the library that can be generally written. To account for that, I wish to be able to fully control the list of terms that go into the function library.

For concreteness, since I try to model a fluid-like system with a 2d field $\mathbf{u}(\mathbf{x}, t)$, I expect convective acceleration $(\mathbf{u}\cdot \nabla) \mathbf{u}$. It will thus results in functions in the form $$f_i = ( u_x \partial_x + u_y \partial_y )u_i.$$ The coefficient in front of both terms is expected to be the same.

Allow for derivatives in the functions of the libraries

I have only been able to generate functions of the form $f(u_x, u_y) \partial_i u$, or $g(u_x, u_y) \partial_i\partial_j u$ (with the derivative_order setting). What about a term which have a squared derivative such as $u_x (\partial_x u_x)^2$ ?

The only workaround I can think of is to consider a 6 dimensional field $(u_i, \partial_i u_j)$ and apply functions to the higher dimensions. But because I don't have a good control over the functions that are considered in the library, this is not satisfying.

tl;dr

I wish to be able to specify each entry in the library function in the form $g = f_0(u) f_1(\nabla u) f_2(\nabla^2 u)$, and freely choose the form for $f_0$, $f_1$ and $f_2$.

If those functionalities already exist, I haven't found a trace of them in the API documentation and example notebooks provided.

Thanks in advance.

Jacob-Stevens-Haas commented 1 month ago

Hey @gdeplus , thanks for your ask. Frankly, i don't know how you even got compositional terms of the form $f(u_x, u_y)$. AFAIK, PDELibrary just multiplies the function library with derivatives, e.g. $f(u)u_x$. e.g.

import numpy as np
import pysindy as ps

(
    ps.PDELibrary(
        ps.PolynomialLibrary(degree=1, include_bias=False),
        derivative_order=2,
        spatial_grid=spatial_grid,
        include_interaction=True
    )
    .fit(np.zeros((10,10,5, 2)))
    .get_feature_names(input_features=["x", "y"])
)

So for composition, you would need to either apply the first transformation in advance, or create a CompositionLibrary object. There's certainly some stuff that can be done with ps.GeneralizedLibrary to restrict certain libraries to certain input variables, or only multiply certain input libraries. If you do build a CompositionLibrary object, think about a PR!

In my opinion, PDELibrary does too much. It's a bit of a God object antipattern, considering TensoredLibrary does much of the same work outside of the actual derivative evaluation. :shrug: