-
Notifications
You must be signed in to change notification settings - Fork 0
/
diffusion_solver.py
144 lines (103 loc) · 3.91 KB
/
diffusion_solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats.qmc as qmc
#high dimensional model
def diffusion( num_samples = 1, min_kappa = 1e-3, max_kappa = 1.1e-3, M = 50, min_U1 = 1.5e-1, max_U1 = 2e-1):
print("starting...\n")
h = 1/M
num_timesteps = 100 #timesteps
dt = 2 #timestep size
GUI = False
#create the del matrix with upwinding
du = 1/h
d = -1/h
dl = 0
#create the matrix in one dimension
exu = np.arange(M - 1)
exl = np.arange(M - 1) + 1
eyu = np.arange(M - 1)
eyl = np.arange(M - 1) + 1
I = np.identity(M)
Ax = I*d
Ax[exu, exu] /= exu + 1
Ax[exu, exu+1] += du/(exu + 1)
Ax[exl, exl-1] += dl/(exl + 1)
Ax[-1, -1] = -1/(h*M)
Ax[-1, -2] = 1/(h*M)
del1 = np.kron(I, Ax)
#create the del^2 matrix with central differences
du= 1/h**2 #upper diagonal value
d = (-2/h**2) #middle diagonal value
dl = du #lower diagonal value
#create the matrix in one dimension
exu = np.arange(M - 1)
exl = np.arange(M - 1) + 1
eyu = np.arange(M - 1)
eyl = np.arange(M - 1) + 1
#set the diagonals for the base matrices
Ax = I*d
Ax[exu, exu + 1] += du
Ax[exl, exl- 1] += dl
Ax[-1,-1] = 0
Ax[-1,-2] = 0
Ax[0,0] = 0
Ax[0,1] = 0
Ay = I*d
Ay[eyu, eyu + 1] += du
Ay[eyl, eyl - 1] += dl
#set the neumann boundary conditions
Ay[-1,-1] = 0
Ay[-1, -2] = 0
Ay[0,0] = 0
Ay[0,1] = 0
del2_y = np.kron(I, Ax)
del2_x = np.kron(Ay, I)
del2 = (del2_y + del2_x)
#set the time stepping matrix with upwinding
d = -1/dt
At = I*d
delt_x = np.kron(I, At)
delt_y = np.kron(At, I)
delt = delt_x + delt_y
sampler = qmc.LatinHypercube(d = 2)
sample = sampler.random(n = num_samples)
sample[:, 0] = (max_kappa - min_kappa)* sample[:, 0] + min_kappa
sample[:, 1] = (max_U1 - min_U1)* sample[:, 1] + min_U1
sample_idx = 0
print("Pe = "+str(sample[0,1]/sample[0,0]))
Fs = np.zeros((num_samples, num_timesteps, M, M))
F = np.zeros((M, M))
F_prev = np.zeros((M, M))
scaling_factors = []
while sample_idx < num_samples:
print("creating sample " + str(sample_idx) + "...\n" )
print("kappa: ", sample[sample_idx, 0])
print("U: ", sample[sample_idx, 1])
#create the right hand side matrix and implement dirichlet boundary conditions
#dirichlet boundary conditions
scaling_factor = sample[sample_idx, 0]/((h**2)) + sample[sample_idx, 1]/(2*h)
scaling_factors.append(scaling_factor)
LHS = sample[sample_idx, 0]*del2 + sample[sample_idx, 1]*del1 + delt #LHS array
t = 0
F_prev = np.zeros((M, M))
F_prev[:,:] = scaling_factor
F_prev[int(np.floor(M/2 -5)):int(np.floor(M/2 + 5)), -1] = 2*scaling_factor
while t < num_timesteps:
print("timestep :", t)
F_eval = F_prev.reshape(M*M,1)
RHS = F_eval
F = np.linalg.solve(-LHS,RHS)
F = F.reshape(M, M)
if GUI:
plt.imshow(F, cmap='viridis')
plt.show()
Fs[sample_idx, t, :, :] = F
F[0,:] = scaling_factor
F[int(np.floor(M/2 -5)):int(np.floor(M/2 + 5)),-1] = 2*scaling_factor
F_prev = F
t += 1
sample_idx += 1
np.save('Fs_sparse_V5.npy', Fs)
np.save('sample_data_sparse_V5.npy', sample)
np.save('scaling_factors_sparse_V5.npy', scaling_factors)
diffusion()