|
|
import numpy as np |
|
|
from scipy.fftpack import idct |
|
|
from scipy.sparse import diags |
|
|
from scipy.interpolate import RectBivariateSpline |
|
|
from scipy.sparse.linalg import spsolve |
|
|
from scipy.sparse import diags, block_diag, bmat |
|
|
|
|
|
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
def GRF(alpha, tau, s): |
|
|
|
|
|
xi = np.random.normal(0, 1, (s, s)) |
|
|
|
|
|
|
|
|
K1, K2 = np.meshgrid(np.arange(s), np.arange(s)) |
|
|
coef = tau**(alpha - 1) * (np.pi**2 * (K1**2 + K2**2) + tau**2)**(-alpha / 2) |
|
|
|
|
|
|
|
|
L = s * coef * xi |
|
|
L[0, 0] = 0 |
|
|
|
|
|
|
|
|
U = idct(idct(L, axis=0, norm='ortho'), axis=1, norm='ortho') |
|
|
|
|
|
return U |
|
|
|
|
|
|
|
|
def solve_gwf(coef, F): |
|
|
K = len(coef) |
|
|
|
|
|
|
|
|
X1, Y1 = np.meshgrid(np.linspace(1/(2*K), (2*K-1)/(2*K), K), |
|
|
np.linspace(1/(2*K), (2*K-1)/(2*K), K)) |
|
|
X2, Y2 = np.meshgrid(np.linspace(0, 1, K), np.linspace(0, 1, K)) |
|
|
|
|
|
|
|
|
interp_coef = RectBivariateSpline(X1[0, :], Y1[:, 0], coef, kx=3, ky=3) |
|
|
coef = interp_coef(X2[0, :], Y2[:, 0], grid=True) |
|
|
|
|
|
interp_F = RectBivariateSpline(X1[0, :], Y1[:, 0], F, kx=3, ky=3) |
|
|
F = interp_F(X2[0, :], Y2[:, 0], grid=True) |
|
|
|
|
|
|
|
|
F = F[1:K-1, 1:K-1] |
|
|
|
|
|
N = (K-2) |
|
|
|
|
|
|
|
|
d = [[diags([np.zeros(N)], [0], shape=(N, N)) for _ in range(N)] for _ in range(N)] |
|
|
|
|
|
|
|
|
for j in range(1, K-1): |
|
|
main_diag = (coef[:-2, j] + coef[1:-1, j])/2 + (coef[2:, j] + coef[1:-1, j])/2 \ |
|
|
+ (coef[1:-1, j-1] + coef[1:-1, j])/2 + (coef[1:-1, j+1] + coef[1:-1, j])/2 |
|
|
upper_diag = -(coef[1:-2, j] + coef[2:-1, j]) / 2 |
|
|
lower_diag = upper_diag |
|
|
|
|
|
d[j-1][j-1] = diags([lower_diag, main_diag, upper_diag], offsets=[-1, 0, 1], shape=(N, N)) |
|
|
|
|
|
if j != K-2: |
|
|
off_diag = - (coef[1:-1, j] + coef[1:-1, j+1]) / 2 |
|
|
d[j-1][j] = diags([off_diag], offsets=[0], shape=(N, N)) |
|
|
d[j][j-1] = d[j-1][j] |
|
|
|
|
|
|
|
|
A = bmat(d, format='csr') * (K-1)**2 |
|
|
|
|
|
|
|
|
F_flat = F.flatten() |
|
|
|
|
|
|
|
|
P_inner = spsolve(A, F_flat).reshape((N, N)) |
|
|
|
|
|
|
|
|
P = np.zeros((K, K)) |
|
|
P[1:-1, 1:-1] = P_inner |
|
|
|
|
|
|
|
|
interp_P = RectBivariateSpline(X2[0, :], Y2[:, 0], P, kx=3, ky=3) |
|
|
P = interp_P(X1[0, :], Y1[:, 0], grid=True).T |
|
|
|
|
|
return P |
|
|
|
|
|
|
|
|
def solve_darcy(alpha=2, tau=3, s=256): |
|
|
""" |
|
|
Solve the Darcy equation using the GWF method |
|
|
tau and alpha are parameters of the covariance C = tau^(2*alpha-2)*(-Laplacian + tau^2 I)^(-alpha) |
|
|
Note that we need alpha > d/2 (here d=2) |
|
|
Laplacian has zero Neumann boundary |
|
|
alpha and tau control smoothness; the bigger they are, the smoother the function |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
x = np.linspace(0, 1, s) |
|
|
y = np.linspace(0, 1, s) |
|
|
X, Y = np.meshgrid(x, y) |
|
|
|
|
|
|
|
|
norm_a = GRF(alpha, tau, s) |
|
|
|
|
|
|
|
|
thresh_a = np.where(norm_a >= 0, 12, 4) |
|
|
|
|
|
|
|
|
f = np.ones((s, s)) |
|
|
|
|
|
|
|
|
|
|
|
thresh_p = solve_gwf(thresh_a, f) |
|
|
|
|
|
return thresh_p |
|
|
|
|
|
if __name__ == "__main__": |
|
|
thresh_p = solve_darcy() |