-
Notifications
You must be signed in to change notification settings - Fork 14
/
demo1d.py
104 lines (88 loc) · 3.43 KB
/
demo1d.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
import numpy as np
import scipy.linalg as sla
import matplotlib.pyplot as plt
import pyamg
from one_D_helmholtz import one_D_helmholtz
# Problem parameters
h = 1024
mesh_h = 1.0 / (float(h) - 1.0)
points_per_wavelength = 15.0
# Retrieve 1-D Helmholtz Operator
omega = (2 * np.pi) / (mesh_h * points_per_wavelength)
data = one_D_helmholtz(h, omega=omega, nplane_waves=2)
A = data['A']
B = data['B']
vertices = data['vertices']
np.random.seed(625)
x0 = np.random.rand(A.shape[0])
b = np.zeros_like(x0)
# Solver Parameters
# Note: the matrix is complex-symmetric, not Hermitian. symmetry = 'symmetric'.
smooth = ('energy', {'krylov': 'gmres'})
SA_solve_args = {'cycle': 'W', 'maxiter': 20,
'tol': 1e-8, 'accel': 'gmres'}
SA_build_args = {'max_levels': 10, 'max_coarse': 5, 'coarse_solver': 'pinv2',
'symmetry': 'symmetric'}
smoother = ('gauss_seidel_nr', {'sweep': 'symmetric', 'iterations': 1})
# Construct solver using the "naive" constant mode for B
sa = pyamg.smoothed_aggregation_solver(A,
B=np.ones((A.shape[0], 1)),
strength=('symmetric', {'theta': 0.0}),
presmoother=smoother,
postsmoother=smoother,
smooth=smooth,
**SA_build_args)
# Solve
residuals = []
x = sa.solve(b, x0=x0, residuals=residuals, **SA_solve_args)
residuals1 = residuals
#print("SA with B=1:")
#for i, r in enumerate(residuals):
# print("residual at iteration {0:2}: {1:^6.2e}".format(i, r))
# Construct solver using the wave-like modes for B
sa = pyamg.smoothed_aggregation_solver(A,
B=B,
strength=('symmetric', {'theta': 0.0}),
presmoother=smoother,
postsmoother=smoother,
smooth=smooth,
**SA_build_args)
# Solve
residuals = []
x = sa.solve(b, x0=x0, residuals=residuals, **SA_solve_args)
residualswave = residuals
#print("SA with B=waves:")
#for i, r in enumerate(residuals):
# print("residual at iteration {0:2}: {1:^6.2e}".format(i, r))
fig, ax = plt.subplots()
ax.semilogy(residuals1, label='AMG with $B=1$')
ax.semilogy(residualswave, label='AMG with $B=$wave')
plt.legend()
ax.set_title('AMG convergence for the 1D Helmholtz problem')
figname = f'./output/1dhelmholtzconv.png'
import sys
if '--savefig' in sys.argv:
plt.savefig(figname, bbox_inches='tight', dpi=150)
else:
plt.show()
# plot B vs. the lowest right singular vector, which represents
# the near null-space, for a segment of the domain
fig, ax = plt.subplots()
indys = np.arange(0, min(75, h))
line_styles = ["-b", "--m", ":k"]
for i in range(B.shape[1]):
ax.plot(vertices[indys, 0], np.real(B[indys, i]),
line_styles[i], label='NNS Mode {}'.format(i))
[U, S, V] = sla.svd(A.todense())
V = V.T.copy()
scale = 0.9 / max(np.real(V[indys, -1]))
ax.plot(vertices[indys, 0], scale * np.real(np.ravel(V[indys, -1])),
line_styles[i + 1], label='Re$(\\nu)$')
ax.set_title('Near Null-Space (NNS) vs. Lowest Right Singular Vector $\\nu$')
plt.legend(framealpha=1.0)
figname = f'./output/1dhelmholtzwaves.png'
import sys
if '--savefig' in sys.argv:
plt.savefig(figname, bbox_inches='tight', dpi=150)
else:
plt.show()