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
Complex numbers in DeepXDE? #284
Comments
The network only uses real numbers. You need to split the read and imag parts of the complex numbers explicitly. |
@AneleNcube Hi, I want to ask if you solved the problem successfully, I have the same question, and I don't know how to change my code to fit the split real and imag number. I really need your help. |
@YouCantRedo Hi, I managed to solve my problem by splitting the real and imag parts as @lululxvi had suggested. I had to include two (instead of one) neural network outputs, one for the real and the other for the imag part of u(x), the surrogate of the solution to the differential equation. Since the particular spatial domain I was dealing with was real-valued (i.e. -1.0 < x < 1.0), separating the real part of the differential equation from the imag was not complicated: I just treated the two parts like a system of differential equations (similar to the DeepXDE example https://github.com/lululxvi/deepxde/blob/master/examples/Lorenz_inverse.py which has more that two outputs and just one input for the real-valued input). That way, I did not need to use a complex data type to represent the complex-valued differential equation that I wanted to solve. I obtained the expected results after running the code This is a snippet from my code where I applied the DeepXDE package to solve an eigenvalue problem with complex eigenpairs:
The rest of the code was more or less the same. Just some extra care needs to be taken when writing out the real and imag parts of the differential equations. But, I think it is possible to avoid the need to expand the differential equation yourself (with pen and paper) when you also apply a package such as pytorch with DeepXDE (but I haven't checked this). In that case, you would only write your differential equation as usual, then let the computer split the differential equation by using np.real(...) and np.imag(...). I hope this might help you overcome your current challenge with your code. I'm not sure exactly why the neural network code cannot handle complex datatypes, perhaps it is something in the source codes for the loss. I will not hazard a guess too much, so I will leave that for @lululxvi to answer. |
Dear @AneleNcube
pde: du_z - con * (du_xx + du_yy)
con = -0.00795224193206157j
|
Hi @YouCantRedo.
Hessian matrix H: H[i][j] = d^2y / dx_i dx_j, where i,j=0,…,dim_x-1. Thus, in this case, unlike the Jacobian matrix, the indices "i" and "j" denote the input variables in the sense that "x_0" is x, "x_1" is y and "x_2" is z . So, to define the second derivative of u2 w.r.t input "x", for example, we must have i = j = 0 so that H[0][0] = d^2 u2 / dx_0 dx_0. The argument "component" in
Regarding the coefficients omega1 and omega2 in my code, they actually appear as In the case of your equation, you have returned the correct expressions since your pde has 1 pure imaginary coefficent.
Like you suggested and as I have done in my code, I had boundary conditions for the real and imaginary parts of the pde. I used the boundary values of my reference solution as Dirichlet boundary conditions. In your code, is "z" the time variable and what are your initial conditions? If the initial conditions are in terms of a function, I think you can try something similar to the code from the example: reaction_inverse https://github.com/lululxvi/deepxde/blob/master/examples/reaction_inverse.py:
Depending on how your initial condition looks like, you can customise this to your equations. Since you have two other inputs (x and y), I suppose you are using dde.geometry.Polygon( ... ) to define the 2-D xy-plane (like in the example: Poisson_Lshape https://github.com/lululxvi/deepxde/blob/master/examples/Poisson_Lshape.py). Yes, I think you would need to define separate boundary conditions for the real and imaginary parts of your differential equation as was done in the Lorenz_Inverse example.
|
Dear @AneleNcube
|
Hi @YouCantRedo. I am glad to discuss and share ideas.
You could save the model every 1000 or so training epochs, then after it has completed training you can use a
This will save your model every n number of epochs as specified in
I tried this with one of my problems and obtained the following plot for the L_2 relative errors. Perhaps there is another much more compact and quick alternative to doing this, but for now I can only think of this "Rube Goldberg-like" approach.
|
@AneleNcube @YouCantRedo The way to provide the solution is to define a function with multiple outputs: def func(X):
real = ... # The real part of the solution, column array
imag = ... # The im part of the solution, column array
return np.hstack((real, imag))
... TimePDE(..., solution=func) |
@AneleNcube Thank you very much for your answer! I have 2 other questions.
return [
I think this approach can achieve the same effect as your code (as shown in Fig2), is this right? |
Thank you @lululxvi and @YouCantRedo.
It works quite well for me too. For gauging the accuracy of your model, perhaps the best metric is L2 relative error which you can add with this piece:
The L2 relative error ought to decrease as the training progresses and I think a good model will have, at most, a L2 relative error 1e-2 or 1e-3. But, it depends on the level of accuracy you need from your model. In the case where you need to get more accurate approximations you may have to train for more epochs. In terms of postprocessing, I can see from your image that you didn't obtain the plots of your solution u(x,y,z) perhaps because it has 3 input variables and 1 response variable. I'm not sure yet how you can get the plots in your scenario, but you may need to write some code for plotting the predicted u(x,y) at different constant values of z. Do you mind sharing your code so that I can try that approach? |
@AneleNcube I would be happy to share the code with you! Can you please leave an email, so I can send it to you! |
My email address: ncubeanele4@gmail.com |
@YouCantRedo @AneleNcube For 3d case, unfortunately, DeepXDE won't plot it for you. You have to predict the solution and plot it by yourself. |
Hi @YouCantRedo and @lululxvi. Thank you for sharing your code @YouCantRedo. I looked at it today and tried to figure out why there is a high L2 relative error (~1e+01) when comparing the model prediction and u_true (the reference solution provided by your npz files). I'm not sure of the reason yet, but I generated some plots comparing the real part of u(x,y,z) as given by u_pred, u_true, and func (the model prediction, reference solution in dataset form, and reference solution in functional form, respectively):
Screenshot of output (u_pred vs. u_true vs. func) These are plots of u(x, y , z=constant) for some values of "z" I chose randomly: z= 0, 1, 25, 50. Notice there seems to be a mismatch between the two reference solutions u_true and func, as seen by the high L2 relative error comparing them and the plots for z= 25 and z=50. However, the two seem to agree for lower values of z, such as z=0 and z=1: Perhaps this mismatch between the reference solutions may explain the low accuracy of the predicted solution? Which reference solution is correct? |
I think i might know why deepxde is not support complex number. In tensorflow backend the tf.gradient can not distinguish the complex number and its conjugate in the last few version. But in the pytorch 1.9.0, they introduce the torch.complex() to solve complex numbers' by using the wirtinger deravitive to solve the autrograd, as you can see in: https://pytorch.org/docs/stable/complex_numbers.html |
@AneleNcube Thank you very much for your work! However, the L2 relative error is still relatively high (~1e-01), and decreases very slow, do you have any idea for this reason. I have sent the new version of my code with correct func to your email address, please feel free to check it! |
@louhz You are welcome to submit a pull request. |
@louhz Thank you very much for your answer! Now I am tring to use the approch provided by @AneleNcube. |
Yes. I am trying to write the code for the TensorFlow version of the hessian and jacobian matrix for the holomorphic functions. I will pull the request after I finish the code. |
Dear contributors to this thread, greetings |
Dear @lululxvi I recently have started learning PINNs on the DeepXDE framework. I have read your communications and found you very helpful with the implementation of the diffusive PDE I would highly appreciate your help if you kindly guide me with corrections on a basic implementation of the scalar Helmholtz equation (time independent) in an unbounded homogeneous medium. It's the wave equation in 2D and its solution should be a plane wave in either of the 2 spatial directions. I shall be grateful if you could have a look at the code below. I have commented on it well and made it very simple. I have the following confusion too:
I shall once again highly acknowledge your help whenever I become able to produce something. looking forward to hearing from you |
I am not sure about this.
Yes.
This may be related to (1).
You can predict the solution at any point after training. |
Is there a way to change the data type in deepxde from float32 to complex32 or complex64? I read the answer given for issue #28 about changing from the default single precision, float32, to double precision, float64, for real floating point numbers. The command used is:
dde.config.real.set_float64()
Is there a similar command for converting to complex numbers, or only real numbers are permitted by deepxde?
The text was updated successfully, but these errors were encountered: