|
2 | 2 | import tensorflow as tf |
3 | 3 | import scipy.io |
4 | 4 | import tensordiffeq as tdq |
5 | | -from tensordiffeq.models import CollocationSolver1D |
6 | | -from tensorflow.domain import DomainND |
7 | | -import math |
8 | | -from tensordiffeq.boundaries import IC, dirichlectBC, periodicBC |
| 5 | +from tensordiffeq.models import DiscoveryModel |
| 6 | +from tensordiffeq.utils import tensor |
9 | 7 |
|
10 | | -def f_model(u_model, x, t): |
11 | | - u = u_model(tf.concat([x,t],1)) |
12 | | - u_x = tf.gradients(u, x) |
13 | | - u_xx = tf.gradients(u_x, x) |
14 | | - u_t = tf.gradients(u,t) |
15 | | - c1 = tdq.utils.constant(.0001) |
16 | | - c2 = tdq.utils.constant(5.0) |
17 | | - f_u = u_t - c1*u_xx + c2*u*u*u - c2*u |
18 | | - return f_u |
19 | | - |
20 | | -def u_x_model(u_model, x, t): |
21 | | - u = u_model(tf.concat([x,t], 1)) |
22 | | - u_x = tf.gradients(u, x) |
23 | | - return u, u_x |
24 | | - |
25 | | - |
26 | | -N0 = 200 |
27 | | -NS = 200 |
28 | | -N_b = 100 |
29 | | -N_f = 20000 |
| 8 | +##################### |
| 9 | +## Discovery Model ## |
| 10 | +##################### |
30 | 11 |
|
31 | | -Domain = DomainND(["x", "t"]) |
32 | 12 |
|
33 | | -Domain.add("x", [-1,1], 512) |
34 | | -Domain.add("t", [0,1], 100) |
| 13 | +# Put params into a list |
| 14 | +params = [tf.Variable(0.0, dtype=tf.float32), tf.Variable(0.0, dtype=tf.float32)] |
35 | 15 |
|
36 | | -def func_ic(x): |
37 | | - return np.sin(x*math.pi) |
38 | | - |
39 | | -BCs = [IC(Domain, func_ic, vars = 'x'), |
40 | | - dirichlectBC(Domain, val = 0.0, vars = 'x', target = "upper"), |
41 | | - dirichlectBC(Domain, val = 0.0, vars = 'x', target = "lower"), |
42 | | - periodicBC(Domain, vars = 'x')] |
43 | | - |
44 | | -col_weights = tf.Variable(tf.random.uniform([N_f, 1])) |
45 | | -u_weights = tf.Variable(100*tf.random.uniform([N0, 1])) |
46 | | - |
47 | | -# Grab collocation points using latin hpyercube sampling |
48 | | -xlimits = np.array([[-1.0, 1.0], [0.0, 1.0]]) |
49 | | -X_f = tdq.LatinHypercubeSample(N_f, xlimits) #x_f, t_f |
50 | 16 |
|
| 17 | +# Define f_model, note the `vars` argument. Inputs must follow this order! |
| 18 | +def f_model(u_model, var, x, t): |
| 19 | + u = u_model(tf.concat([x, t], 1)) |
| 20 | + u_x = tf.gradients(u, x) |
| 21 | + u_xx = tf.gradients(u_x, x) |
| 22 | + u_t = tf.gradients(u, t) |
| 23 | + c1 = var[0] # tunable param 1 |
| 24 | + c2 = var[1] # tunable param 2 |
| 25 | + f_u = u_t - c1 * u_xx + c2 * u * u * u - c2 * u |
| 26 | + return f_u |
51 | 27 |
|
52 | | -lb = np.array([-1.0]) |
53 | | -ub = np.array([1.0]) |
54 | 28 |
|
55 | 29 | # Import data, same data as Raissi et al |
56 | 30 |
|
57 | 31 | data = scipy.io.loadmat('AC.mat') |
58 | 32 |
|
59 | | -t = data['tt'].flatten()[:,None] |
60 | | -x = data['x'].flatten()[:,None] |
| 33 | +t = data['tt'].flatten()[:, None] |
| 34 | +x = data['x'].flatten()[:, None] |
61 | 35 | Exact = data['uu'] |
62 | 36 | Exact_u = np.real(Exact) |
63 | 37 |
|
64 | | -#grab training points from domain |
65 | | -idx_x = np.random.choice(x.shape[0], N0, replace=False) |
66 | | -x0 = x[idx_x,:] |
67 | | -u0 = tf.cast(Exact_u[idx_x,0:1], dtype = tf.float32) |
68 | | - |
69 | | -idx_xs = np.random.choice(x.shape[0], NS, replace=False) #need multiple Xs |
70 | | -idx_ts = 100 #for 1 t value |
71 | | -y_s = Exact[idx_xs, idx_ts] |
72 | | -x_s = x[idx_xs,:] |
73 | | -t_s = np.repeat(t[idx_ts,:], len(x_s)) |
74 | | - |
75 | | -y_s = tf.cast(tf.reshape(y_s, (-1,1)), dtype = tf.float32) #tensors need to be of shape (NS, 1), not (NS, ) |
76 | | -x_s = tdq.tensor(x_s) |
77 | | -t_s = tf.cast(tf.reshape(t_s, (-1,1)), dtype = tf.float32) |
78 | | - |
79 | | -idx_t = np.random.choice(t.shape[0], N_b, replace=False) |
80 | | -tb = t[idx_t,:] |
81 | | - |
82 | | -# Grab collocation points using latin hpyercube sampling |
83 | | -x_f = tf.convert_to_tensor(X_f[:,0:1], dtype=tf.float32) |
84 | | -t_f = tf.convert_to_tensor(np.abs(X_f[:,1:2]), dtype=tf.float32) |
85 | | - |
86 | | - |
87 | | -X0 = np.concatenate((x0, 0*x0), 1) # (x0, 0) |
88 | | -X_lb = np.concatenate((0*tb + lb[0], tb), 1) # (lb[0], tb) |
89 | | -X_ub = np.concatenate((0*tb + ub[0], tb), 1) # (ub[0], tb) |
90 | | - |
91 | | -x0 = tf.cast(X0[:,0:1], dtype = tf.float32) |
92 | | -t0 = tf.cast(X0[:,1:2], dtype = tf.float32) |
93 | | - |
94 | | -x_lb = tf.convert_to_tensor(X_lb[:,0:1], dtype=tf.float32) |
95 | | -t_lb = tf.convert_to_tensor(X_lb[:,1:2], dtype=tf.float32) |
96 | | - |
97 | | -x_ub = tf.convert_to_tensor(X_ub[:,0:1], dtype=tf.float32) |
98 | | -t_ub = tf.convert_to_tensor(X_ub[:,1:2], dtype=tf.float32) |
99 | | - |
| 38 | +# define MLP depth and layer width |
100 | 39 | layer_sizes = [2, 128, 128, 128, 128, 1] |
101 | | -model = CollocationSolver1D(assimilate = True) |
102 | | - |
103 | | -def g(lam): |
104 | | - return lam**2 |
105 | | - |
106 | | -model.compile(layer_sizes, f_model, x_f, t_f, x0, t0, u0, x_lb, t_lb, x_ub, t_ub, isPeriodic=True, u_x_model=u_x_model) |
107 | | -model.compile_data(x_s, t_s, y_s) |
108 | | - |
109 | | -#train loop |
110 | | -model.fit(tf_iter = 5000, newton_iter = 5000) |
111 | 40 |
|
112 | | -#generate meshgrid for forward pass of u_pred |
113 | | -X, T = np.meshgrid(x,t) |
| 41 | +# generate all combinations of x and t |
| 42 | +X, T = np.meshgrid(x, t) |
114 | 43 |
|
115 | | -X_star = np.hstack((X.flatten()[:,None], T.flatten()[:,None])) |
116 | | -u_star = Exact_u.T.flatten()[:,None] |
| 44 | +X_star = np.hstack((X.flatten()[:, None], T.flatten()[:, None])) |
| 45 | +u_star = Exact_u.T.flatten()[:, None] |
117 | 46 |
|
118 | | -u_pred, f_u_pred = model.predict(X_star) |
| 47 | +x = X_star[:, 0:1] |
| 48 | +t = X_star[:, 1:2] |
119 | 49 |
|
120 | | -error_u = tdq.find_L2_error(u_pred, u_star) |
121 | | -print('Error u: %e' % (error_u)) |
| 50 | +print(np.shape(x)) |
| 51 | +# append to a list for input to model.fit |
| 52 | +X = [x, t] |
122 | 53 |
|
123 | | -U_pred = tdq.get_griddata(X_star, u_pred.flatten(), (X,T)) |
124 | | -FU_pred = tdq.get_griddata(X_star, f_u_pred.flatten(), (X,T)) |
| 54 | +# define col_weights for SA discovery model |
| 55 | +col_weights = tf.Variable(tf.random.uniform([np.shape(x)[0], 1])) |
125 | 56 |
|
126 | | -lb = np.array([-1.0, 0.0]) |
127 | | -ub = np.array([1.0, 1]) |
| 57 | +# initialize, compile, train model |
| 58 | +model = DiscoveryModel() |
| 59 | +model.compile(layer_sizes, f_model, X, u_star, params, |
| 60 | + col_weights=col_weights) # baseline approach can be done by simply removing the col_weights arg |
| 61 | +model.tf_optimizer_weights = tf.keras.optimizers.Adam(lr=0.005, |
| 62 | + beta_1=.95) # an example as to how one could modify an optimizer, in this case the col_weights optimizer |
128 | 63 |
|
129 | | -tdq.plotting.plot_solution_domain1D(model, [x, t], ub = ub, lb = lb, Exact_u=Exact_u) |
| 64 | +# train loop |
| 65 | +model.fit(tf_iter=10000) |
130 | 66 |
|
131 | | -extent = [0.0, 1.0, -1.0, 1.0] |
132 | | -tdq.plotting.plot_residuals(FU_pred, extent) |
| 67 | +# doesnt work quite yet |
| 68 | +tdq.plotting.plot_weights(model, scale=10.0) |
0 commit comments