Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing piece-wise PDEs #185

Closed
andyxzhu opened this issue Dec 23, 2020 · 6 comments
Closed

Implementing piece-wise PDEs #185

andyxzhu opened this issue Dec 23, 2020 · 6 comments

Comments

@andyxzhu
Copy link

Hi @lululxvi, thanks for the excellent library.

I am interested in creating a PDE to be learned by the neural network that depends on an input condition.

For instance, from example ode_system.py:

def ode_system(x, y):
    """ODE system.
    dy1/dx = y2
    dy2/dx = -y1
    """
    y1, y2 = y[:, 0:1], y[:, 1:]
    dy1_x = dde.grad.jacobian(y, x, i=0)
    dy2_x = dde.grad.jacobian(y, x, i=1)
    return [dy1_x - y2, dy2_x + y1]

This solves dy1/dx = y2 and dy2/dx = -y1.

What if I wanted it to solve those equations if x in [0,10], then solve for a different condition like dy1/dx = 0 and dy2/dx = 1 if x in (10, 100] using y1(10) and y2(10) as the new "initial" conditions?

Is there a way to get just one network to learn this instead of training multiple networks for each piece? I tried implementing this by changing my PDE function, but eager execution is disabled even though I'm running TF 2.

Many thanks.

@lululxvi
Copy link
Owner

You need to combine these two cases in one ODE as dy1/dt = f1(t, y1, y2) and dy2/dt = f2(t, y1, y2), and then everything is the same. There might be more than one solutions to define f1 and f2, such that f1 and f2 depend on t. One way is that you can use tf.math.sign (https://www.tensorflow.org/api_docs/python/tf/math/sign) to define f1 and f2.

@andyxzhu
Copy link
Author

Could you clarify how to use tf.sign() to define f1 and f2 on arbitrary connected intervals, such as [0,10] and (10, 20]? Right now I have this:

def ode_system(x, y):
    """ODE system.
    dy1/dx = y2
    dy2/dx = -y1
    """
    y1, y2 = y[:, 0:1], y[:, 1:]
    dy1_x = dde.grad.jacobian(y, x, i=0)
    dy2_x = dde.grad.jacobian(y, x, i=1)
    signs = tf.sign(x)
    return [dy1_x - signs*y2, dy2_x + signs*y1]

The only way I can see this being useful is if I wanted to define dy1/dx = y2 and dy2/dx = -y1 on a positive interval like (0, 10), then the negative version dy1/dx = -y2 and dy2/dx = y1 on a negative interval like (-10, 0) (this is what I got when I solved it from (-10, 10) with IC f1(-10) = sin(-10) and f2(-10) = -cos(-10) ).
download (6)

Can I instead use tf.sign() to make it solve any function on any interval, though? Thanks!

@lululxvi
Copy link
Owner

You can use tf.sign(x-a) if the break point is a.

@andyxzhu
Copy link
Author

Thank you for the advice, but I've found an alternate approach with tf.where. Cheers!

@engsbk
Copy link
Contributor

engsbk commented Feb 8, 2021

@azhu529 Did you have to change the last layer of your network to be [2] instead [1] for two different outputs since you have a piecewise function in the output?

as in:
net = dde.maps.FNN([2] + [35] * 4 + [2], "tanh", "Glorot normal")
instead of:
net = dde.maps.FNN([2] + [35] * 4 + [1], "tanh", "Glorot normal")

@andyxzhu
Copy link
Author

andyxzhu commented Feb 8, 2021

Yes, the output layer was [2].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants