deepxde icon indicating copy to clipboard operation
deepxde copied to clipboard

Matrix form of "A simple ODE system"

Open louisricoeur opened this issue 2 years ago • 7 comments

Dear @lululxvi and team,

I have been trying to replicate the "A simple ODE system" example with the ODE specified in a matrix form - before adapting it to my specific problem. I got the message: InvalidArgumentError: Incompatible shapes: [39,1] vs. [2,39] [[{{node sub_200}}]]

The only part I changed was the one involving the ODE system:

A = np.array([[0, 1], [-1, 0]])
A_tf = tf.convert_to_tensor(A, dtype=tf.float32)

def ode_deepxde(x, y):
    lhs = dde.grad.jacobian(y, x)
    rhs = tf.matmul(A_tf, y, transpose_b=True)
    return lhs - rhs

Now A_tf is a 2x2 matrix, y should be a 1x2 vector and dde.grad.jacobian(y, x) should be a 2x1 vector. Could you please help me trouble shoot this issue? Thank you.

I have already looked the Lotka-Volterra example where tf.matmul is used, but could not adapt it successfully.

louisricoeur avatar Aug 27 '22 10:08 louisricoeur

Instead of using the matrix form, I think you just need to derive that 2x2 matrix into 2 equations.It means you will have 2 residuals. Plz following the tutorial.

haison19952013 avatar Aug 28 '22 15:08 haison19952013

Thank you for your answer.

However, the objective is then to apply the technique to my specific application, where I have a linear system with 8x8 matrix which is the outcome of an algorithm. So it would be way more convenient to be able to use the matrix directly, rather than manually specify dy1_x etc.

So your suggestion does not solve the problem unfortunately.

louisricoeur avatar Aug 28 '22 17:08 louisricoeur

Please put the full trackback of the error inside the code snippet i.e. <> icon in the toolbar.

When you say "ODE specified in a matrix form" i guess you are talking about the global equilibrium equation for example, stiffness*displacement-force = 0? Is that correct?

praksharma avatar Aug 30 '22 14:08 praksharma

Dear @praksharma, thank you for coming back to me regarding this topic.

  • When I say "ODE specified in a matrix form", I mean any ODE written in the form dy/dt = Ay, where y is a nx1 column vector and A is a mxn matrix.

For the specific system given in "A simple ODE system", it means writing the ODE as dy/dt = Ay where: A = \begin{matrix} 0 & 1\ -1 & 0 \end{matrix}.

  • Regarding the full trackback of the error, please find it below:

InvalidArgumentError Traceback (most recent call last) File /usr/local/anaconda3/envs/DeepXDE/lib/python3.10/site-packages/tensorflow/python/client/session.py:1377, in BaseSession._do_call(self, fn, *args) 1376 try: -> 1377 return fn(*args) 1378 except errors.OpError as e:

File /usr/local/anaconda3/envs/DeepXDE/lib/python3.10/site-packages/tensorflow/python/client/session.py:1360, in BaseSession._do_run.<locals>._run_fn(feed_dict, fetch_list, target_list, options, run_metadata) 1359 self._extend_graph() -> 1360 return self._call_tf_sessionrun(options, feed_dict, fetch_list, 1361 target_list, run_metadata)

File /usr/local/anaconda3/envs/DeepXDE/lib/python3.10/site-packages/tensorflow/python/client/session.py:1453, in BaseSession._call_tf_sessionrun(self, options, feed_dict, fetch_list, target_list, run_metadata) 1451 def _call_tf_sessionrun(self, options, feed_dict, fetch_list, target_list, 1452 run_metadata): -> 1453 return tf_session.TF_SessionRun_wrapper(self._session, options, feed_dict, 1454 fetch_list, target_list, 1455 run_metadata)

InvalidArgumentError: Incompatible shapes: [39,1] vs. [2,39] [[{{node sub}}]]

` During handling of the above exception, another exception occurred:

InvalidArgumentError Traceback (most recent call last) ... File "/usr/local/anaconda3/envs/DeepXDE/lib/python3.10/site-packages/tensorflow/python/framework/ops.py", line 3754, in _create_op_internal ret = Operation( File "/usr/local/anaconda3/envs/DeepXDE/lib/python3.10/site-packages/tensorflow/python/framework/ops.py", line 2133, in init self._traceback = tf_stack.extract_stack_for_node(self._c_op) `

  • For the record, the full code I am using is:
import numpy as np
A = np.array([[0, 1], [-1, 0]])

def ode_deepxde(x, y):
    lhs = dde.grad.jacobian(y, x)
    rhs = tf.matmul(A_tf, y, transpose_b=True)
    return lhs - rhs

geom = dde.geometry.TimeDomain(0, Tf)
def boundary(_, on_initial):
    return on_initial
ic1 = dde.icbc.IC(geom, lambda x: 0, boundary, component=0)
ic2 = dde.icbc.IC(geom, lambda x: 1, boundary, component=1)
data = dde.data.PDE(geom, ode_deepxde, [ic1, ic2], 35, 2, num_test=100)
layer_size = [1] + [50] * 3 + [A.shape[0]]
activation = "tanh"
initializer = "Glorot uniform"
net = dde.nn.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr=0.001)
losshistory, train_state = model.train(iterations=20000, display_every=100)

louisricoeur avatar Sep 08 '22 16:09 louisricoeur

InvalidArgumentError: Incompatible shapes: [39,1] vs. [2,39].

You might want to replace

rhs = tf.matmul(A_tf, y, transpose_b=False)

I didn't run your code.

praksharma avatar Sep 09 '22 06:09 praksharma

Just implementing the change you suggested leads to another, similar error:

InvalidArgumentError: Matrix size-incompatible: In[0]: [2,2], In[1]: [39,2] [[{{node MatMul}}]]

Changing this same line in the following way does not lead to an error message, but the solution is completely off, which should not be the case given that writting the ODE in a matrix form is (mathematically) equivalent to specifying it line by line and that the same code works when the ODE is specified line by line:

rhs = tf.matmul(y, A_tf, transpose_b=True)

Same comment goes when changing this same line to:

rhs = tf.matmul(y, A_tf, transpose_b=False)

I am a bit puzzled at what to try next.

louisricoeur avatar Sep 09 '22 08:09 louisricoeur

Note that y has the shape batch_size x N.

lululxvi avatar Sep 14 '22 19:09 lululxvi

I just went through the same problem. If it may help anyone, here it is the full code which can be easily extended to the case in which N >> 1.

import deepxde as dde
import numpy as np

A_tf = np.array([[0, 1], [-1, 0]], dtype = 'float64')
n = 2

def ode_deepxde(x, y):
    lhs0 = dde.grad.jacobian(y, x, i = 0, j = 0)
    for a in range(1,n):
        lhsa = dde.grad.jacobian(y, x, i = a, j = 0)
        lhs  = tf.squeeze(tf.stack((lhs0, lhsa), axis = 1), axis = 2)
    rhs = tf.einsum('jk,kl->jl', A_tf, tf.transpose(y))
    return lhs - tf.transpose(rhs)

geom = dde.geometry.TimeDomain(0, 10)

def boundary(x, on_initial):
    return np.isclose(x[0], 0)

ic1 = dde.icbc.IC(geom, lambda x: 0, boundary, component=0)
ic2 = dde.icbc.IC(geom, lambda x: 1, boundary, component=1)

def func(x):
    return np.hstack((np.sin(x), np.cos(x)))

data = dde.data.PDE(geom, ode_deepxde, [ic1, ic2], 35, 2, num_test=100, solution=func)

layer_size = [1] + [50] * 3 + [2]
activation = "tanh"
initializer = "Glorot uniform"
net = dde.nn.FNN(layer_size, activation, initializer)

model = dde.Model(data, net)
model.compile("adam", lr=0.001, metrics=["l2 relative error"])
losshistory, train_state = model.train(iterations=20000, display_every=100)

download_1 download

riccardotomada avatar Nov 19 '22 13:11 riccardotomada