├── Icon.png
├── FAU_MoD_Internship_Report__PINN.pdf
├── degenerate_wave.m
├── README.md
├── second_case_damage.py
├── first_case_no_damage.py
├── control.py
├── test_loss_time.py
├── third_case_double_damage.py
├── Wave_equation.py
├── train_error_val_error_time.py
├── wave_equation_otherBC.py
├── Inverse_problem.py
├── all_together_loss_time.py
└── changing_nodes_test_loss.py
/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DCN-FAU-AvH/PINNs_wave_equation/HEAD/Icon.png
--------------------------------------------------------------------------------
/FAU_MoD_Internship_Report__PINN.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DCN-FAU-AvH/PINNs_wave_equation/HEAD/FAU_MoD_Internship_Report__PINN.pdf
--------------------------------------------------------------------------------
/degenerate_wave.m:
--------------------------------------------------------------------------------
1 | clear all
2 | close all
3 | clc
4 |
5 | alpha = 0;
6 | a =@(x) 4*(2*norm(x-0.5))^alpha; % stiffness
7 | u0 = @(x) sin(pi*x/2); % initial condition
8 |
9 | L = 1;
10 | N = 100;
11 | x = linspace(0,L);
12 | dx = x(2) - x(1);
13 |
14 | A = sparse(N,N);
15 | A(1,1) = -2*a(x(1)); A(1,2) = 2*a(x(1));
16 | for ii = 2:N-1
17 | A(ii,ii-1) = 1*a(x(ii));
18 | A(ii,ii) = -2*a(x(ii));
19 | A(ii,ii+1) = 1*a(x(ii));
20 | end
21 | A(N,N-1) = 2*a(x(N)); A(N,N) = -2*a(x(N));
22 | A = A/dx^2;
23 |
24 | T = 2;
25 | NT = 400;
26 | time = linspace(0,T,NT);
27 | dt = time(2) - time(1);
28 |
29 | U = zeros(N,NT);
30 | U(:,1) = u0(x); % zero velocity initial condition
31 | U(:,2) = u0(x);
32 |
33 | cdofs = [1]; % nodes with Dirichlet BCs
34 | fdofs = setdiff(1:N, cdofs);
35 |
36 | for ii = 3:NT
37 | U(fdofs,ii) = 2*U(fdofs,ii-1) - U(fdofs,ii-2) + dt^2*A(fdofs,fdofs)*U(fdofs,ii-1);
38 | end
39 |
40 | figure
41 | surf(time,fliplr(x),U)
42 | xlabel 'time'
43 | ylabel 'x'
44 | ax = gca;
45 | ax.YTick = [0, 0.5, 1];
46 | ax.YTickLabel = {'1', '0.5', '0'};
47 | zlabel 'solution'
48 | shading interp
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Approximating the 1D wave equation using Physics Informed Neural Networks (PINNs)
2 |
3 | An implementation of Physics-Informed Neural Networks (PINNs) to solve various forward and inverse problems for the 1 dimensional wave equation.
4 |
5 |
6 |
7 |
8 |
9 | ## Detailed explanation
10 |
11 | [Wave_equation.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/Wave_equation.py) solves the 1d wave equation
12 |
13 | [Wave_equation_otherBC](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/Wave_equation_otherBC.py) solves the 1d wave equation with Neumann boundary conditions
14 |
15 | [test_loss_time.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/test_loss_time.py) shows the test error-computational time dependency for a specific structure of neural network
16 |
17 | [train_error_val_error_time.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/train_error_val_error_time.py) displays the train error/validation error/computational time-size of training set dependencies
18 |
19 | [all_together_loss_time.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/all_together_loss_time.py) shows the test error-computational time dependency for different structures of neural networks.
20 |
21 | [changing_nodes_test_loss.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/changing_nodes_test_loss.py) shows the test error-computational time dependency for neural network structures with different numbers of nodes.
22 |
23 | [inverse_problem.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/inverse_problem.py) solves the inverse problem of the 1d wave equation
24 |
25 | [first_case_no_damage.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/first_case_no_damage.py) solves the degenerating 1d wave equation when $a(x)=4$
26 |
27 | [second_case_damage.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/second_case_damage.py) solves the degenerating 1d wave equation when $a(x)=8|x-0.5|$
28 |
29 | [third_case_double_damage.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/third_case_double_damage.py) solves the degenerating 1d wave equation when $a(x)=16|x-0.5|^2$
30 |
31 | [control.py](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/control.py) solves the null controllability problem of the 1d wave equation.
32 |
33 | [degenerate_wave.m](https://github.com/DCN-FAU-AvH/PINNs_wave_equation/blob/main/degenerate_wave.m) solves a wave equation $u_{tt}(t,x) + a(x) u_{xx}(t,x) = 0$ on $x \in (0,1)$ in which the stiffness is $a(x) = 4(2|x-\frac{1}{2}|)^\alpha$ by finite differences. (used for comparison)
34 |
--------------------------------------------------------------------------------
/second_case_damage.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from itertools import product
3 | import deepxde as dde
4 | import math
5 | import pathlib
6 | import os
7 | import tensorflow as tf
8 | import matplotlib.pyplot as plt
9 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
10 | if not OUTPUT_DIRECTORY.exists():
11 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
12 |
13 |
14 |
15 | #first case a(x)=1
16 |
17 | #def a(x,y):
18 | # if x<0.5:
19 | # return 0.5-x
20 | # else:
21 | # return x-0.5
22 |
23 |
24 |
25 | def pde(x, y): # wave equation
26 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
27 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
28 |
29 | return dy_tt - 8*abs(0.5-x[:,0:1])*dy_xx
30 |
31 |
32 | def initial_pos(x): # initial position
33 |
34 | return np.sin((np.pi * x[:, 0:1])/2)
35 |
36 |
37 | def initial_velo(x): # initial velocity
38 |
39 | return 0.0
40 |
41 |
42 | def boundary_left(x, on_boundary): # boundary x=0
43 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
44 |
45 | return is_on_boundary_left
46 |
47 | def boundary_right(x, on_boundary): # boundary x=1
48 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
49 |
50 | return is_on_boundary_right
51 |
52 | def boundary_bottom(x, on_boundary): # boundary t=0
53 | is_on_boundary_bottom = (
54 | on_boundary
55 | and np.isclose(x[1], 0)
56 | and not np.isclose(x[0], 0)
57 | and not np.isclose(x[0], 1)
58 | )
59 |
60 | return is_on_boundary_bottom
61 |
62 |
63 | def boundary_upper(x, on_boundary): # boundary t=2
64 | is_on_boundary_upper = (
65 | on_boundary
66 | and np.isclose(x[1], 2)
67 | and not np.isclose(x[0], 0)
68 | and not np.isclose(x[0], 1)
69 | )
70 |
71 | return is_on_boundary_upper
72 |
73 |
74 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
75 |
76 |
77 | #bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
78 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
79 | #bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
80 | bc2 = dde.NeumannBC(geom, lambda x: 0, boundary_right) #correct
81 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
82 |
83 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
84 |
85 |
86 |
87 |
88 | data = dde.data.PDE(
89 | geom,
90 | pde,
91 | [bc1, bc2, bc3, bc4],
92 | num_domain=2000,
93 | num_boundary=1000, train_distribution="uniform"
94 | )
95 | print("The training set is {}".format(data.train_x_all.T))
96 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
97 |
98 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
99 |
100 | model = dde.Model(data, net)
101 |
102 | model.compile("adam", lr=0.001)
103 |
104 | model.train(epochs=7000)
105 |
106 | model.compile("L-BFGS-B")
107 |
108 | losshistory, train_state = model.train()
109 |
110 | dde.saveplot(
111 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
112 | )
113 |
114 |
115 |
116 | #Post-processing: error analysis and figures
117 |
118 |
119 | X = np.linspace(0, 1, 2000)
120 | t = np.linspace(0, 2, 4000)
121 |
122 | X_repeated = np.repeat(X, t.shape[0])
123 | t_tiled = np.tile(t, X.shape[0])
124 | XX = np.vstack((X_repeated, t_tiled)).T
125 |
126 | state_predict = model.predict(XX).T
127 | state_predict_M = state_predict.reshape((2000, 4000)).T
128 |
129 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 2000), np.linspace(0, 2, 4000))
130 |
131 | fig = plt.figure() # plot of predicted state
132 | ax = plt.axes(projection="3d")
133 | surf = ax.plot_surface(
134 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
135 | )
136 |
137 | ax.set_title(r"PINN state: $a(x)=8|x-\frac{1}{2}|$")
138 | ax.set_xlabel("$x$")
139 | ax.set_ylabel("$t$")
140 | fig.colorbar(surf, shrink=0.6, aspect=10)
141 |
142 | plt.show()
143 |
144 |
145 |
--------------------------------------------------------------------------------
/first_case_no_damage.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from matplotlib import cm
3 | import numpy as np
4 | from itertools import product
5 | import deepxde as dde
6 | import math
7 | import pathlib
8 | import os
9 |
10 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
11 | if not OUTPUT_DIRECTORY.exists():
12 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
13 |
14 |
15 |
16 | #first case a(x)=1
17 |
18 |
19 |
20 | def pde(x, y): # wave equation
21 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
22 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
23 |
24 | return dy_tt - 4*dy_xx
25 |
26 |
27 | def initial_pos(x): # initial position
28 |
29 | return np.sin((np.pi * x[:, 0:1])/2)
30 |
31 |
32 | def initial_velo(x): # initial velocity
33 |
34 | return 0.0
35 |
36 |
37 | def boundary_left(x, on_boundary): # boundary x=0
38 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
39 |
40 | return is_on_boundary_left
41 |
42 | def boundary_right(x, on_boundary): # boundary x=1
43 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
44 |
45 | return is_on_boundary_right
46 |
47 | def boundary_bottom(x, on_boundary): # boundary t=0
48 | is_on_boundary_bottom = (
49 | on_boundary
50 | and np.isclose(x[1], 0)
51 | and not np.isclose(x[0], 0)
52 | and not np.isclose(x[0], 1)
53 | )
54 |
55 | return is_on_boundary_bottom
56 |
57 |
58 | def boundary_upper(x, on_boundary): # boundary t=2
59 | is_on_boundary_upper = (
60 | on_boundary
61 | and np.isclose(x[1], 2)
62 | and not np.isclose(x[0], 0)
63 | and not np.isclose(x[0], 1)
64 | )
65 |
66 | return is_on_boundary_upper
67 |
68 |
69 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
70 |
71 |
72 | #bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
73 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
74 | #bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
75 | bc2 = dde.NeumannBC(geom, lambda x: 0, boundary_right) #correct
76 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
77 |
78 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
79 |
80 |
81 |
82 |
83 | data = dde.data.PDE(
84 | geom,
85 | pde,
86 | [bc1, bc2, bc3, bc4],
87 | num_domain=800,
88 | num_boundary=600, train_distribution="uniform")
89 | #print("The training set is {}".format(data.train_x_all.T))
90 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
91 |
92 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
93 |
94 | model = dde.Model(data, net)
95 |
96 | model.compile("adam", lr=0.001)
97 |
98 | model.train(epochs=7000)
99 |
100 | model.compile("L-BFGS-B")
101 |
102 | losshistory, train_state = model.train()
103 |
104 | dde.saveplot(
105 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
106 | )
107 |
108 |
109 |
110 | #Post-processing: error analysis and figures
111 |
112 | xx=np.linspace(0,1,100)
113 | tt=np.linspace(0,2,200)
114 |
115 |
116 |
117 | X = np.linspace(0, 1, 1000)
118 | t = np.linspace(0, 2, 2000)
119 |
120 | X_repeated = np.repeat(X, t.shape[0])
121 | t_tiled = np.tile(t, X.shape[0])
122 | XX = np.vstack((X_repeated, t_tiled)).T
123 |
124 | state_predict = model.predict(XX).T
125 | state_predict_M = state_predict.reshape((1000, 2000)).T
126 |
127 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 1000), np.linspace(0, 2, 2000))
128 |
129 | fig = plt.figure() # plot of predicted state
130 | ax = plt.axes(projection="3d")
131 | surf = ax.plot_surface(
132 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
133 | )
134 |
135 | ax.set_title("PINN state: a(x)=4")
136 | ax.set_xlabel("$x$")
137 | ax.set_ylabel("$t$")
138 | fig.colorbar(surf, shrink=0.6, aspect=10)
139 |
140 | plt.show()
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/control.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from matplotlib import cm
3 | import numpy as np
4 | from itertools import product
5 | import deepxde as dde
6 | import math
7 | import pathlib
8 | import os
9 |
10 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
11 | if not OUTPUT_DIRECTORY.exists():
12 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
13 |
14 |
15 | def pde(x, y): # wave equation
16 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
17 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
18 |
19 | return dy_tt - 4*dy_xx
20 |
21 |
22 | def initial_pos(x): # initial position
23 |
24 | return np.sin(np.pi * x[:, 0:1])
25 |
26 |
27 | def initial_velo(x): # initial velocity
28 |
29 | return 0.0
30 |
31 |
32 | def boundary_left(x, on_boundary): # boundary x=0
33 | is_on_boundary_left =on_boundary and np.isclose(x[0], 0)
34 | return is_on_boundary_left
35 |
36 | #def boundary_right(x, on_boundary): # boundary x=1
37 | # is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
38 |
39 | # return is_on_boundary_right
40 |
41 | def boundary_bottom(x, on_boundary): # boundary t=0
42 | is_on_boundary_bottom = (
43 | on_boundary
44 | and np.isclose(x[1], 0)
45 | and not np.isclose(x[0], 0)
46 | and not np.isclose(x[0], 1)
47 | )
48 |
49 | return is_on_boundary_bottom
50 |
51 |
52 | def boundary_upper(x, on_boundary): # boundary t=4
53 | is_on_boundary_upper = (
54 | on_boundary
55 | and np.isclose(x[1], 4) and not np.isclose(x[0], 0) and not np.isclose(x[0], 1)
56 |
57 | )
58 |
59 | return is_on_boundary_upper
60 |
61 |
62 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 4])
63 |
64 |
65 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
66 |
67 | #bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
68 |
69 | bc2 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
70 |
71 | bc3 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
72 |
73 |
74 |
75 | bc4 = dde.DirichletBC(geom, lambda x: 0, boundary_upper) #correct
76 |
77 | bc5 = dde.NeumannBC(geom, initial_velo, boundary_upper) #correct
78 |
79 |
80 | data = dde.data.PDE(
81 | geom,
82 | pde,
83 | [bc1, bc2, bc3, bc4, bc5],
84 | num_domain=1000,
85 | num_boundary=700,
86 | )
87 | print("The training set is {}".format(data.train_x_all.T))
88 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
89 |
90 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
91 |
92 | model = dde.Model(data, net)
93 |
94 | model.compile("adam", lr=0.001)
95 |
96 | model.train(epochs=10000)
97 |
98 | model.compile("L-BFGS-B")
99 |
100 | losshistory, train_state = model.train()
101 |
102 | dde.saveplot(
103 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
104 | )
105 |
106 |
107 | X = np.linspace(0, 1, 600)
108 | t = np.linspace(0, 4, 2400)
109 |
110 | X_repeated = np.repeat(X, t.shape[0])
111 | t_tiled = np.tile(t, X.shape[0])
112 | XX = np.vstack((X_repeated, t_tiled)).T
113 |
114 | state_predict = model.predict(XX).T
115 | state_predict_M = state_predict.reshape((600, 2400)).T
116 |
117 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 600), np.linspace(0, 4, 2400))
118 |
119 | fig = plt.figure() # plot of predicted state
120 | ax = plt.axes(projection="3d")
121 | surf = ax.plot_surface(
122 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
123 | )
124 |
125 | ax.set_title("PINN state ")
126 | ax.set_xlabel("$x$")
127 | ax.set_ylabel("$t$")
128 | fig.colorbar(surf, shrink=0.6, aspect=10)
129 |
130 | plt.show()
131 |
132 |
133 |
134 | tt = np.linspace(0, 4, 40000)
135 | xx1 = np.ones_like(tt)
136 | X1 = np.vstack((xx1, tt)).T
137 |
138 |
139 | control_predict_1 = np.ravel(model.predict(X1)) # predicted control1
140 | control_predict_1[0]=0
141 |
142 |
143 |
144 | fig=plt.figure()
145 | plt.plot(tt, control_predict_1, label="Control function u(t)", color="r")
146 | plt.xlabel("t")
147 | plt.ylabel("u(t)")
148 | plt.legend()
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/test_loss_time.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from matplotlib import cm
3 | import numpy as np
4 | from itertools import product
5 | import deepxde as dde
6 | import math
7 | import pathlib
8 | import os
9 | import time
10 | #import tf.keras.callbacks.EarlyStopping
11 | import tensorflow as tf
12 | from toolz import partition
13 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "wave_equation"
14 | if not OUTPUT_DIRECTORY.exists():
15 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
16 |
17 |
18 | def pde(x, y): # wave equation
19 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
20 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
21 |
22 | return dy_tt - 4*dy_xx
23 |
24 |
25 | def initial_pos(x): # initial position
26 |
27 | return np.sin(np.pi * x[:, 0:1])
28 |
29 |
30 | def initial_velo(x): # initial velocity
31 |
32 | return 0.0
33 |
34 |
35 | def boundary_left(x, on_boundary): # boundary x=0
36 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
37 |
38 | return is_on_boundary_left
39 |
40 | def boundary_right(x, on_boundary): # boundary x=1
41 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
42 |
43 | return is_on_boundary_right
44 |
45 | def boundary_bottom(x, on_boundary): # boundary t=0
46 | is_on_boundary_bottom = (
47 | on_boundary
48 | and np.isclose(x[1], 0)
49 | and not np.isclose(x[0], 0)
50 | and not np.isclose(x[0], 1)
51 | )
52 |
53 | return is_on_boundary_bottom
54 |
55 |
56 | def boundary_upper(x, on_boundary): # boundary t=2
57 | is_on_boundary_upper = (
58 | on_boundary
59 | and np.isclose(x[1], 2)
60 | and not np.isclose(x[0], 0)
61 | and not np.isclose(x[0], 1)
62 | )
63 |
64 | return is_on_boundary_upper
65 |
66 | def func(x):
67 | return np.sin(np.pi * x[:, 0:1]) * np.cos(2*np.pi*x[:, 1:])
68 |
69 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
70 |
71 |
72 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
73 |
74 | bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
75 |
76 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
77 |
78 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
79 |
80 |
81 |
82 |
83 | data = dde.data.TimePDE(
84 | geom,
85 | pde,
86 | [bc1, bc2, bc3, bc4],
87 | num_domain=200,
88 | num_boundary=100, solution=func, num_test=250
89 | )
90 | print("The training set is {}".format(data.train_x_all.T))
91 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
92 |
93 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
94 |
95 | #callback=dde.callbacks.EarlyStopping(min_delta=0.001, patience=1000, monitor='loss_test')
96 |
97 | model = dde.Model(data, net)
98 |
99 | model.compile("adam", lr=0.001)
100 |
101 | class TimeHistory(dde.callbacks.Callback):
102 | #def __init__(self):
103 | #self.times = []
104 | def on_train_begin(self):
105 | self.times = []
106 | # self.time0=[] #everything started
107 | # self.timef=[] #everything ended
108 | def on_epoch_begin(self):
109 | self.epoch_time_start = time.process_time()
110 | # self.time0.append(self.epoch_time_start)
111 | def on_epoch_end(self):
112 | self.times.append(time.process_time() - self.epoch_time_start)
113 | # self.epoch_time_end = time.process_time()
114 | # self.timef.append(self.epoch_time_end)
115 |
116 |
117 | time_callback = TimeHistory()
118 | history=model.train(callbacks=[time_callback], epochs=10000)
119 | def fun(x):
120 | x=np.array(x)
121 | return np.sum(x)
122 | #print(len(time_callback.times))
123 | chunks_1 = list(partition(1000, time_callback.times))
124 | #print(time_callback.times)
125 | time_epochs=list(map(fun, chunks_1))
126 | print("Time epochs {}".format(time_epochs))
127 | model.compile("L-BFGS-B")
128 | print("Time epochs {}".format(time_epochs))
129 |
130 |
131 |
132 | losshistory, train_state = model.train()
133 |
134 |
135 |
136 |
137 | dde.saveplot(
138 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
139 | )
140 | print("Loss history gives {}".format(losshistory.loss_train))
141 |
142 |
143 | print("Loss history gives {}".format(losshistory.metrics_test))
144 |
145 |
146 | a=list(map(np.sum, losshistory.loss_test))[0:10]
147 | print("Total loss is {}".format(a))
148 |
149 |
150 |
151 |
152 | print("This are the times {}".format(time_epochs))
153 | print("This are the test losses {}".format(losshistory.loss_test[0:10]))
154 |
155 | time_taken=[]
156 | b=0
157 | for i in range(len(time_epochs)):
158 | b=b+time_epochs[i]
159 | time_taken.append(b)
160 |
161 |
162 | plt.plot(time_taken, a)
163 | plt.xlabel("Computational time (s)")
164 | plt.ylabel("Test error")
165 | plt.title("Test error vs. Computational time")
166 |
167 | print("Comp. time: {}".format(time_taken))
168 | print("Error: {}".format(a))
--------------------------------------------------------------------------------
/third_case_double_damage.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from itertools import product
3 | import deepxde as dde
4 | import math
5 | import pathlib
6 | import os
7 | import tensorflow as tf
8 | import matplotlib.pyplot as plt
9 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
10 | if not OUTPUT_DIRECTORY.exists():
11 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
12 |
13 |
14 |
15 | #first case a(x)=1
16 |
17 | #def a(x,y):
18 | # if x<0.5:
19 | # return 0.5-x
20 | # else:
21 | # return x-0.5
22 |
23 |
24 |
25 | def pde(x, y): # wave equation
26 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
27 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
28 |
29 | return dy_tt - 16*abs(0.5-x[:,0:1])**2*dy_xx
30 |
31 |
32 | def initial_pos(x): # initial position
33 |
34 | return np.sin((np.pi * x[:, 0:1])/2)
35 |
36 |
37 | def initial_velo(x): # initial velocity
38 |
39 | return 0.0
40 |
41 |
42 | def boundary_left(x, on_boundary): # boundary x=0
43 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
44 |
45 | return is_on_boundary_left
46 |
47 | def boundary_right(x, on_boundary): # boundary x=1
48 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
49 |
50 | return is_on_boundary_right
51 |
52 | def boundary_bottom(x, on_boundary): # boundary t=0
53 | is_on_boundary_bottom = (
54 | on_boundary
55 | and np.isclose(x[1], 0)
56 | and not np.isclose(x[0], 0)
57 | and not np.isclose(x[0], 1)
58 | )
59 |
60 | return is_on_boundary_bottom
61 |
62 |
63 | def boundary_upper(x, on_boundary): # boundary t=2
64 | is_on_boundary_upper = (
65 | on_boundary
66 | and np.isclose(x[1], 2)
67 | and not np.isclose(x[0], 0)
68 | and not np.isclose(x[0], 1)
69 | )
70 |
71 | return is_on_boundary_upper
72 |
73 |
74 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
75 |
76 |
77 | #bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
78 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
79 | #bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
80 | bc2 = dde.NeumannBC(geom, lambda x: 0, boundary_right) #correct
81 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
82 |
83 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
84 |
85 |
86 |
87 |
88 | data = dde.data.PDE(
89 | geom,
90 | pde,
91 | [bc1, bc2, bc3, bc4],
92 | num_domain=400,
93 | num_boundary=800,
94 | )
95 | print("The training set is {}".format(data.train_x_all.T))
96 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
97 |
98 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
99 |
100 | model = dde.Model(data, net)
101 |
102 | model.compile("adam", lr=0.001)
103 |
104 | model.train(epochs=7000)
105 |
106 | model.compile("L-BFGS-B")
107 |
108 | losshistory, train_state = model.train()
109 |
110 | dde.saveplot(
111 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
112 | )
113 |
114 |
115 |
116 | #Post-processing: error analysis and figures
117 |
118 | xx=np.linspace(0,1,1000)
119 | tt=np.linspace(0,2,2000)
120 | #X_repeated = np.repeat(xx, tt.shape[0])
121 | #t_tiled = np.tile(tt, xx.shape[0])
122 | #X=np.vstack((X_repeated, t_tiled)).T
123 | list_all_data=list(product(*[list(xx), list(tt)], repeat=1))
124 | #print("List all data is {}".format(list_all_data))
125 | #X=[np.asarray(list_all_data[k]) for k in range(len(list_all_data))]
126 | #X=np.asarray(X)
127 | print("List {}".format(list_all_data))
128 | training_set=[(data.train_x_all.T[0][k], data.train_x_all.T[1][k]) for k in range(len(data.train_x_all.T[0]))]
129 |
130 | gen_error_set=set(list_all_data)-set(training_set)
131 | l1=list(gen_error_set)
132 | print("li is {}".format(l1))
133 | validating_set=[np.asarray(l1[k]) for k in range(len(l1))]
134 | print("Dania {}".format(validating_set))
135 | validating_set=np.asarray(validating_set)
136 | print("Dania 2 {}".format(validating_set))
137 | #print("Validating set {}".format(validating_set))
138 | predicted_solution = np.ravel(model.predict(validating_set))
139 | print("Pred solution {}".format(predicted_solution))
140 |
141 | X = np.linspace(0, 1, 1000)
142 | t = np.linspace(0, 2, 2000)
143 |
144 |
145 | X_repeated = np.repeat(X, t.shape[0])
146 | t_tiled = np.tile(t, X.shape[0])
147 | XX = np.vstack((X_repeated, t_tiled)).T
148 |
149 | state_predict = model.predict(XX).T
150 | state_predict_M = state_predict.reshape((1000, 2000)).T
151 |
152 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 1000), np.linspace(0, 2, 2000))
153 |
154 | fig = plt.figure() # plot of predicted state
155 | ax = plt.axes(projection="3d")
156 | surf = ax.plot_surface(
157 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
158 | )
159 |
160 | ax.set_title(r"PINN state: $a(x)=16|x-\frac{1}{2}|^{2}$")
161 | ax.set_xlabel("$x$")
162 | ax.set_ylabel("$t$")
163 | fig.colorbar(surf, shrink=0.6, aspect=10)
164 |
165 | plt.show()
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/Wave_equation.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from matplotlib import cm
3 | import numpy as np
4 | from itertools import product
5 | import deepxde as dde
6 | import math
7 | import pathlib
8 | import os
9 |
10 |
11 |
12 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "wave_equation"
13 | if not OUTPUT_DIRECTORY.exists():
14 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
15 |
16 |
17 | def pde(x, y): # wave equation
18 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
19 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
20 |
21 | return dy_tt - 4*dy_xx
22 |
23 |
24 | def initial_pos(x): # initial position
25 |
26 | return np.sin(np.pi * x[:, 0:1])
27 |
28 |
29 | def initial_velo(x): # initial velocity
30 |
31 | return 0.0
32 |
33 |
34 | def boundary_left(x, on_boundary): # boundary x=0
35 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
36 |
37 | return is_on_boundary_left
38 |
39 | def boundary_right(x, on_boundary): # boundary x=1
40 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
41 |
42 | return is_on_boundary_right
43 |
44 | def boundary_bottom(x, on_boundary): # boundary t=0
45 | is_on_boundary_bottom = (
46 | on_boundary
47 | and np.isclose(x[1], 0)
48 | and not np.isclose(x[0], 0)
49 | and not np.isclose(x[0], 1)
50 | )
51 |
52 | return is_on_boundary_bottom
53 |
54 |
55 | def boundary_upper(x, on_boundary): # boundary t=2
56 | is_on_boundary_upper = (
57 | on_boundary
58 | and np.isclose(x[1], 2)
59 | and not np.isclose(x[0], 0)
60 | and not np.isclose(x[0], 1)
61 | )
62 |
63 | return is_on_boundary_upper
64 |
65 | def func(x):
66 | return np.sin(np.pi * x[:, 0:1]) * np.cos(2*np.pi*x[:, 1:])
67 |
68 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
69 |
70 |
71 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
72 |
73 | bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
74 |
75 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
76 |
77 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
78 |
79 |
80 |
81 |
82 | data = dde.data.TimePDE(
83 | geom,
84 | pde,
85 | [bc1, bc2, bc3, bc4],
86 | num_domain=100,
87 | num_boundary=50, solution=func
88 | )
89 | print("The training set is {}".format(data.train_x_all.T))
90 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
91 |
92 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
93 |
94 |
95 | model = dde.Model(data, net)
96 |
97 | model.compile("adam", lr=0.001)
98 |
99 | model.train(epochs=8000)
100 |
101 | model.compile("L-BFGS-B")
102 |
103 | losshistory, train_state = model.train()
104 |
105 | dde.saveplot(
106 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
107 | )
108 |
109 |
110 |
111 | #Post-processing: error analysis and figures
112 |
113 | xx=np.linspace(0,1,100)
114 | tt=np.linspace(0,2,200)
115 |
116 | list_all_data=list(product(*[list(xx), list(tt)], repeat=1))
117 |
118 |
119 | training_set=[(data.train_x_all.T[0][k], data.train_x_all.T[1][k]) for k in range(len(data.train_x_all.T[0]))]
120 |
121 |
122 | def exact_function(x):
123 | return math.sin(math.pi*x[0])*math.cos(2*math.pi*x[1])
124 |
125 |
126 |
127 | X = np.linspace(0, 1, 100)
128 | t = np.linspace(0, 2, 200)
129 |
130 | X_repeated = np.repeat(X, t.shape[0])
131 | t_tiled = np.tile(t, X.shape[0])
132 | XX = np.vstack((X_repeated, t_tiled)).T
133 |
134 | state_predict = model.predict(XX).T
135 | state_predict_M = state_predict.reshape((100, 200)).T
136 |
137 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 100), np.linspace(0, 2, 200))
138 |
139 | fig = plt.figure() # plot of predicted state
140 | ax = plt.axes(projection="3d")
141 | surf = ax.plot_surface(
142 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
143 | )
144 |
145 | ax.set_title("PINN state ")
146 | ax.set_xlabel("$x$")
147 | ax.set_ylabel("$t$")
148 | fig.colorbar(surf, shrink=0.6, aspect=10)
149 |
150 | plt.show()
151 |
152 |
153 | def explicit_state(x,t):
154 | return np.sin(math.pi*x)*np.cos(2*math.pi*t)
155 |
156 |
157 | state_exact = explicit_state(Xx, Tt) # computation of exact state
158 |
159 | fig = plt.figure() # plot of exact state
160 | ax = plt.axes(projection="3d")
161 | surf2 = ax.plot_surface(
162 | Xx, Tt, state_exact, cmap="hsv_r", linewidth=0, antialiased=False
163 | )
164 |
165 | ax.set_title("Exact state ")
166 | ax.set_xlabel("$x$")
167 | ax.set_ylabel("$t$")
168 |
169 | fig.colorbar(surf2, shrink=0.6, aspect=10)
170 |
171 | plt.show()
172 |
173 |
174 |
175 | fig = plt.figure() # plot of the difference between exact and PINN state
176 | ax = plt.axes(projection="3d")
177 | surf2 = ax.plot_surface(
178 | Xx, Tt, state_exact-state_predict_M, cmap="hsv_r",
179 | linewidth=0, antialiased=False
180 | )
181 |
182 | ax.set_title("Difference of the exact and PINN state")
183 | ax.set_xlabel("$x$")
184 | ax.set_ylabel("$t$")
185 |
186 | fig.colorbar(surf2, shrink=0.6, aspect=10)
187 |
188 | plt.show()
189 |
190 |
191 | #Plot the training set and validation set
192 | fig = plt.figure()
193 |
194 | plt.plot(data.train_x_all.T[0], data.train_x_all.T[1],"o")
195 | #plt.plot(validating_set.T[0], validating_set.T[1], "r", label="Validation set")
196 | plt.xlabel("x")
197 | plt.ylabel("t")
198 | plt.title("Training set")
199 | #plt.legend()
200 |
201 |
202 |
--------------------------------------------------------------------------------
/train_error_val_error_time.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | t0=time.process_time()
4 | import matplotlib.pyplot as plt
5 | from matplotlib import cm
6 | import numpy as np
7 | from itertools import product
8 | import deepxde as dde
9 | import math
10 | import pathlib
11 | import os
12 |
13 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
14 | if not OUTPUT_DIRECTORY.exists():
15 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
16 |
17 |
18 | def pde(x, y): # wave equation
19 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
20 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
21 |
22 | return dy_tt - 4*dy_xx
23 |
24 |
25 | def initial_pos(x): # initial position
26 |
27 | return np.sin(np.pi * x[:, 0:1])
28 |
29 |
30 | def initial_velo(x): # initial velocity
31 |
32 | return 0.0
33 |
34 |
35 | def boundary_left(x, on_boundary): # boundary x=0
36 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
37 |
38 | return is_on_boundary_left
39 |
40 | def boundary_right(x, on_boundary): # boundary x=1
41 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
42 |
43 | return is_on_boundary_right
44 |
45 | def boundary_bottom(x, on_boundary): # boundary t=0
46 | is_on_boundary_bottom = (
47 | on_boundary
48 | and np.isclose(x[1], 0)
49 | and not np.isclose(x[0], 0)
50 | and not np.isclose(x[0], 1)
51 | )
52 |
53 | return is_on_boundary_bottom
54 |
55 |
56 | def boundary_upper(x, on_boundary): # boundary t=2
57 | is_on_boundary_upper = (
58 | on_boundary
59 | and np.isclose(x[1], 2)
60 | and not np.isclose(x[0], 0)
61 | and not np.isclose(x[0], 1)
62 | )
63 |
64 | return is_on_boundary_upper
65 |
66 | def func(x):
67 | return np.sin(np.pi * x[:, 0:1]) * np.cos(2*np.pi*x[:, 1:])
68 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
69 |
70 |
71 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
72 |
73 | bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
74 |
75 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
76 |
77 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
78 |
79 |
80 |
81 | data=[]
82 | models=[]
83 | net = dde.maps.FNN([2] + [50] * 4 + [1],"tanh", "Glorot uniform")
84 | xx=np.linspace(0,1,600)
85 | tt=np.linspace(0,2,600)
86 | list_all_data=list(product(*[list(xx), list(tt)], repeat=1))
87 | gen_err=[]
88 | train_err=[]
89 | training_set_all=[]
90 | compiling_time=[]
91 | def exact_function(x):
92 | return math.sin(math.pi*x[0])*math.cos(2*math.pi*x[1])
93 |
94 |
95 |
96 | for k in range(6):
97 | observe_x_1_val=np.vstack((np.linspace(0, 1, num=199-10*k), np.full((199-10*k), 2))).T
98 | observe_x_1 = np.vstack((np.linspace(0, 1, num=1+10*k), np.full((1+10*k), 2))).T
99 | observe_x_2_val=np.vstack((np.linspace(0, 1, num=199-10*k), np.full((199-10*k), 0))).T
100 | observe_x_2 = np.vstack((np.linspace(0, 1, num=1+10*k), np.full((1+10*k), 0))).T
101 | observe_x_3_val=np.vstack((np.full((199-10*k), 0),np.linspace(0, 2, num=199-10*k))).T
102 | observe_x_3 = np.vstack((np.full((1+10*k), 0),np.linspace(0, 2, num=1+10*k))).T
103 | observe_x_4_val=np.vstack((np.full((199-10*k), 1),np.linspace(0, 2, num=199-10*k))).T
104 | observe_x_4 = np.vstack((np.full((1+10*k), 1),np.linspace(0, 2, num=1+10*k))).T
105 | observe_x_5_val=np.vstack((np.full((199-10*k), 0.5),np.linspace(0, 2, num=199-10*k))).T
106 | observe_x_5=np.vstack((np.full((1+10*k), 0.5),np.linspace(0, 2, num=1+10*k))).T
107 | observe_x_6_val=np.vstack((np.linspace(0, 1, num=199-10*k), np.full((199-10*k), 1))).T
108 | observe_x_6=np.vstack((np.linspace(0, 1, num=1+10*k), np.full((1+10*k), 1))).T
109 |
110 | observe_x=np.array(list(observe_x_1)+list(observe_x_2)+list(observe_x_3)+list(observe_x_4)+list(observe_x_6)+list(observe_x_5))
111 | # print(observe_x)
112 | observe_final_val=np.array(list(observe_x_1_val)+list(observe_x_2_val)+list(observe_x_3_val)+list(observe_x_4_val)+list(observe_x_5_val)+list(observe_x_6_val))
113 | #print(len(observe_final_val)
114 | # observe_final_val1=[(observe_final_val.T[0][i], observe_final_val.T[1][i]) for i in range(len(observe_final_val.T[0]))
115 |
116 | observe_final_val1=[(observe_final_val.T[0][i], observe_final_val.T[1][i]) for i in range(len(observe_final_val.T[0]))]
117 | # print(observe_final_val1)
118 | training_set=[(observe_x.T[0][i], observe_x.T[1][i]) for i in range(len(observe_x.T[0]))]
119 | # print(training_set)
120 | gen_err_set=set(observe_final_val1)-set(training_set)
121 | # print(gen_err_set)
122 | l1=list(gen_err_set)
123 | validating_set=[np.asarray(l1[i]) for i in range(len(l1))]
124 | #print(validating_set)
125 | observe_y=dde.icbc.PointSetBC(observe_x, func(observe_x), component=0)
126 | data = dde.data.PDE(geom, pde, [bc1, bc2, bc3, bc4, observe_y], num_domain=0, num_boundary=0,anchors=observe_x,num_test=1000, solution=func)
127 | model = dde.Model(data, net)
128 | #models.append(model)
129 | model.compile("adam", lr=0.001, loss_weights=[1,1,1,1,1,1])
130 | model.train(epochs=6000)
131 | model.compile("L-BFGS-B", loss_weights=[1,1,1,1,1,1])
132 | losshistory, train_state=model.train()
133 |
134 | predicted_solution = np.ravel(model.predict(validating_set))
135 | exact_solution=np.asarray(list(map(exact_function, validating_set)))
136 | # gen_error = (1/len(predicted_solution))*np.linalg.norm(predicted_solution - exact_solution)
137 | gen_error = (1/len(predicted_solution))*np.sum(predicted_solution**2 + exact_solution**2-2*predicted_solution*exact_solution)
138 | gen_err.append(gen_error)
139 | training_error=np.sum(np.array(losshistory.loss_train[-1]))
140 | train_err.append(training_error)
141 | compiling_time.append(time.process_time()-t0)
142 |
143 |
144 | no_samples=[6+k*60 for k in range(6)]
145 |
146 | fig = plt.figure()
147 | plt.plot(no_samples, gen_err, color="red",marker="o", linestyle="-")
148 | #plot.plot(x, y, color="red", marker="o", linestyle="--")
149 | plt.xlabel("No. training samples")
150 | plt.ylabel("Validation error")
151 | plt.title("Validation error vs. no of training samples")
152 | plt.show()
153 | plt.savefig("Generr.png")
154 |
155 |
156 | fig = plt.figure() # plot of predicted state
157 | plt.plot(no_samples, train_err, marker="o", linestyle="-")
158 | plt.xlabel("No. training samples")
159 | plt.ylabel("Training error")
160 | plt.title("Training error vs. no of training samples")
161 | plt.show()
162 | plt.savefig("Trainerr.png")
163 |
164 |
165 |
166 | fig = plt.figure() # plot of predicted state
167 | plt.plot(no_samples, compiling_time, color="green",marker="o", linestyle="-")
168 | plt.xlabel("No. training samples")
169 | plt.ylabel("Computational time")
170 | plt.title("Computational time vs. no of training samples")
171 | plt.show()
172 | plt.savefig("Time.png")
173 |
174 |
--------------------------------------------------------------------------------
/wave_equation_otherBC.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from matplotlib import cm
3 | import numpy as np
4 | from itertools import product
5 | import deepxde as dde
6 | import math
7 | import pathlib
8 | import os
9 |
10 | OUTPUT_DIRECTORY = pathlib.Path.cwd() / "results" / "linear_wave"
11 | if not OUTPUT_DIRECTORY.exists():
12 | os.makedirs(OUTPUT_DIRECTORY, exist_ok=True)
13 |
14 |
15 | def pde(x, y): # wave equation
16 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
17 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
18 |
19 | return dy_tt - 4*dy_xx
20 |
21 |
22 | def initial_pos(x): # initial position
23 |
24 | return np.sin(np.pi * x[:, 0:1])
25 |
26 |
27 | def initial_velo(x): # initial velocity
28 |
29 | return 0.0
30 |
31 |
32 | def boundary_left(x, on_boundary): # boundary x=0
33 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
34 |
35 | return is_on_boundary_left
36 |
37 | def boundary_right(x, on_boundary): # boundary x=1
38 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
39 |
40 | return is_on_boundary_right
41 |
42 | def boundary_bottom(x, on_boundary): # boundary t=0
43 | is_on_boundary_bottom = (
44 | on_boundary
45 | and np.isclose(x[1], 0)
46 | and not np.isclose(x[0], 0)
47 | and not np.isclose(x[0], 1)
48 | )
49 |
50 | return is_on_boundary_bottom
51 |
52 |
53 | def boundary_upper(x, on_boundary): # boundary t=2
54 | is_on_boundary_upper = (
55 | on_boundary
56 | and np.isclose(x[1], 2)
57 | and not np.isclose(x[0], 0)
58 | and not np.isclose(x[0], 1)
59 | )
60 |
61 | return is_on_boundary_upper
62 |
63 |
64 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
65 |
66 |
67 | #bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
68 | bc1 = dde.NeumannBC(geom, lambda x: 0, boundary_left) #correct
69 | #bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
70 | bc2 = dde.NeumannBC(geom, lambda x: 0, boundary_right) #correct
71 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
72 |
73 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
74 |
75 |
76 |
77 |
78 | data = dde.data.PDE(
79 | geom,
80 | pde,
81 | [bc1, bc2, bc3, bc4],
82 | num_domain=200,
83 | num_boundary=100,
84 | )
85 | print("The training set is {}".format(data.train_x_all.T))
86 | net = dde.maps.FNN([2] + [50] * 4 + [1], "tanh", "Glorot uniform") #the input layer has size 2, there are 4 hidden layers of size 50 and one output layer of size 1
87 |
88 | #Activation function is tanh; the weights are initially chosen to be uniformly distributed according to Glorat distribution
89 |
90 | model = dde.Model(data, net)
91 |
92 | model.compile("adam", lr=0.001)
93 |
94 | model.train(epochs=7000)
95 |
96 | model.compile("L-BFGS-B")
97 |
98 | losshistory, train_state = model.train()
99 |
100 | dde.saveplot(
101 | losshistory, train_state, issave=True, isplot=True, output_dir=OUTPUT_DIRECTORY
102 | )
103 |
104 |
105 |
106 | #Post-processing: error analysis and figures
107 |
108 | xx=np.linspace(0,1,100)
109 | tt=np.linspace(0,2,200)
110 | #X_repeated = np.repeat(xx, tt.shape[0])
111 | #t_tiled = np.tile(tt, xx.shape[0])
112 | #X=np.vstack((X_repeated, t_tiled)).T
113 | list_all_data=list(product(*[list(xx), list(tt)], repeat=1))
114 | #print("List all data is {}".format(list_all_data))
115 | #X=[np.asarray(list_all_data[k]) for k in range(len(list_all_data))]
116 | #X=np.asarray(X)
117 | print("List {}".format(list_all_data))
118 | training_set=[(data.train_x_all.T[0][k], data.train_x_all.T[1][k]) for k in range(len(data.train_x_all.T[0]))]
119 |
120 | gen_error_set=set(list_all_data)-set(training_set)
121 | l1=list(gen_error_set)
122 | print("li is {}".format(l1))
123 | validating_set=[np.asarray(l1[k]) for k in range(len(l1))]
124 | print("Dania {}".format(validating_set))
125 | validating_set=np.asarray(validating_set)
126 | print("Dania 2 {}".format(validating_set))
127 | #print("Validating set {}".format(validating_set))
128 | predicted_solution = np.ravel(model.predict(validating_set))
129 | print("Pred solution {}".format(predicted_solution))
130 | def exact_function(x):
131 | return math.sin(math.pi*x[0])*math.cos(2*math.pi*x[1])
132 |
133 | #Generalization error:
134 | exact_solution=np.asarray(list(map(exact_function, validating_set)))
135 | print("Exact solution {}".format(exact_solution))
136 | gen_error = (1/len(predicted_solution))*np.linalg.norm(predicted_solution - exact_solution)
137 | print("Generalization error is {}".format(gen_error))
138 | relative_error = np.linalg.norm(predicted_solution - exact_solution) / np.linalg.norm(exact_solution)
139 | print("Relative error is {}".format(relative_error))
140 | #Training error:
141 | exact_solution_training=np.asarray(list(map(exact_function, data.train_x_all)))
142 | predicted_solution_training=np.ravel(model.predict(data.train_x_all))
143 | training_error=(1/len(predicted_solution_training))*np.linalg.norm(predicted_solution_training- exact_solution_training)
144 | X = np.linspace(0, 1, 100)
145 | t = np.linspace(0, 2, 200)
146 |
147 | X_repeated = np.repeat(X, t.shape[0])
148 | t_tiled = np.tile(t, X.shape[0])
149 | XX = np.vstack((X_repeated, t_tiled)).T
150 |
151 | state_predict = model.predict(XX).T
152 | state_predict_M = state_predict.reshape((100, 200)).T
153 |
154 | Xx, Tt = np.meshgrid(np.linspace(0, 1, 100), np.linspace(0, 2, 200))
155 |
156 | fig = plt.figure() # plot of predicted state
157 | ax = plt.axes(projection="3d")
158 | surf = ax.plot_surface(
159 | Xx, Tt, state_predict_M, cmap="hsv_r", linewidth=0, antialiased=False
160 | )
161 |
162 | ax.set_title("PINN state ")
163 | ax.set_xlabel("$x$")
164 | ax.set_ylabel("$t$")
165 | fig.colorbar(surf, shrink=0.6, aspect=10)
166 |
167 | plt.show()
168 |
169 |
170 | def explicit_state(x,t):
171 | return np.sin(math.pi*x)*np.cos(2*math.pi*t)
172 |
173 |
174 | state_exact = explicit_state(Xx, Tt) # computation of exact state
175 |
176 | fig = plt.figure() # plot of exact state
177 | ax = plt.axes(projection="3d")
178 | surf2 = ax.plot_surface(
179 | Xx, Tt, state_exact, cmap="hsv_r", linewidth=0, antialiased=False
180 | )
181 |
182 | ax.set_title("Exact state ")
183 | ax.set_xlabel("$x$")
184 | ax.set_ylabel("$t$")
185 |
186 | fig.colorbar(surf2, shrink=0.6, aspect=10)
187 |
188 | plt.show()
189 |
190 |
191 |
192 | fig = plt.figure() # plot of the difference between exact and PINN state
193 | ax = plt.axes(projection="3d")
194 | surf2 = ax.plot_surface(
195 | Xx, Tt, state_exact-state_predict_M, cmap="hsv_r",
196 | linewidth=0, antialiased=False
197 | )
198 |
199 | ax.set_title("Difference of the exact and PINN state")
200 | ax.set_xlabel("$x$")
201 | ax.set_ylabel("$t$")
202 |
203 | fig.colorbar(surf2, shrink=0.6, aspect=10)
204 |
205 | plt.show()
206 |
207 |
208 | #Plot the training set and validation set
209 | fig = plt.figure()
210 |
211 | plt.plot(data.train_x_all.T[0], data.train_x_all.T[1],"o")
212 | #plt.plot(validating_set.T[0], validating_set.T[1], "r", label="Validation set")
213 | plt.xlabel("x")
214 | plt.ylabel("t")
215 | plt.title("Training set")
216 | #plt.legend()
217 |
218 |
219 | print("Training set {}".format(data.train_x_all))
220 | #print("Validation set {}".format(validating_set))
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
--------------------------------------------------------------------------------
/Inverse_problem.py:
--------------------------------------------------------------------------------
1 | import deepxde as dde
2 | import numpy as np
3 | # Backend tensorflow.compat.v1 or tensorflow
4 | from deepxde.backend import tf
5 | # Backend pytorch
6 | # import torch
7 | # Backend paddle
8 | # import paddle
9 | import matplotlib.pyplot as plt
10 | Ctrue=4.0
11 | C = dde.Variable(0.05)
12 |
13 | def pde(x, y): # wave equation
14 | dy_tt = dde.grad.hessian(y, x, i=1, j=1)
15 | dy_xx = dde.grad.hessian(y, x, i=0, j=0)
16 | return dy_tt - C*dy_xx
17 |
18 | def initial_pos(x): # initial position
19 | return np.sin(np.pi * x[:, 0:1])
20 |
21 | def initial_velo(x): # initial velocity
22 | return 0.0
23 |
24 |
25 | def boundary_left(x, on_boundary): # boundary x=0
26 | is_on_boundary_left = on_boundary and np.isclose(x[0], 0)
27 | return is_on_boundary_left
28 |
29 | def boundary_right(x, on_boundary): # boundary x=1
30 | is_on_boundary_right = on_boundary and np.isclose(x[0], 1)
31 | return is_on_boundary_right
32 |
33 | def boundary_bottom(x, on_boundary): # boundary t=0
34 | is_on_boundary_bottom = (
35 | on_boundary
36 | and np.isclose(x[1], 0)
37 | and not np.isclose(x[0], 0)
38 | and not np.isclose(x[0], 1)
39 | )
40 |
41 | return is_on_boundary_bottom
42 |
43 |
44 | def boundary_upper(x, on_boundary): # boundary t=2
45 | is_on_boundary_upper = (
46 | on_boundary
47 | and np.isclose(x[1], 2)
48 | and not np.isclose(x[0], 0)
49 | and not np.isclose(x[0], 1)
50 | )
51 |
52 | return is_on_boundary_upper
53 |
54 | def func(x):
55 | return np.sin(np.pi * x[:, 0:1]) * np.cos(2*np.pi*x[:, 1:])
56 |
57 | #geom = dde.geometry.Interval(0, 1)
58 | #timedomain = dde.geometry.TimeDomain(0, 2)
59 | #geomtime = dde.geometry.GeometryXTime(geom, timedomain)
60 |
61 | geom = dde.geometry.Rectangle(xmin=[0, 0], xmax=[1, 2])
62 |
63 |
64 | bc1 = dde.DirichletBC(geom, lambda x: 0, boundary_left) #correct
65 |
66 | bc2 = dde.DirichletBC(geom, lambda x: 0, boundary_right) #correct
67 |
68 | bc3 = dde.DirichletBC(geom, initial_pos, boundary_bottom) #correct
69 |
70 | bc4 = dde.NeumannBC(geom, initial_velo, boundary_bottom) #correct
71 |
72 |
73 | observe_x_1 = np.vstack((np.linspace(0, 1, num=200), np.full((200), 2))).T
74 | observe_x_2 = np.vstack((np.linspace(0, 1, num=200), np.full((200), 0))).T
75 | observe_x_3 = np.vstack((np.full((200), 0),np.linspace(0, 2, num=200))).T
76 | observe_x_4 = np.vstack((np.full((200), 1),np.linspace(0, 2, num=200))).T
77 |
78 |
79 | observe_x_initial = np.random.uniform((0, 0), (1, 2), (1000, 2))
80 | observe_x_5=np.array([a for a in observe_x_initial if 0