Skip to content

Commit 1bc13f9

Browse files
committed
Merge pull request #38 from danielru/boussinesq/selectable_order
Boussinesq/selectable order
2 parents dd1fb97 + e72d23c commit 1bc13f9

File tree

15 files changed

+649
-222
lines changed

15 files changed

+649
-222
lines changed

examples/SWFW/playground.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,21 @@
1919
logger = Log.setup_custom_logger('root')
2020

2121
num_procs = 1
22+
23+
N_s = 100
24+
N_f = 125
2225

2326
# This comes as read-in for the level class
2427
lparams = {}
2528
lparams['restol'] = 1E-12
2629

2730
sparams = {}
28-
sparams['maxiter'] = 2
31+
sparams['maxiter'] = 4
2932

3033
# This comes as read-in for the problem class
3134
pparams = {}
32-
pparams['lambda_s'] = 1j*np.linspace(0,3,100)
33-
pparams['lambda_f'] = 1j*np.linspace(0,8,100)
35+
pparams['lambda_s'] = 1j*np.linspace(0.0, 4.0, N_s)
36+
pparams['lambda_f'] = 1j*np.linspace(0.0, 8.0, N_f)
3437
pparams['u0'] = 1
3538

3639
# Fill description dictionary for easy hierarchy creation
@@ -40,7 +43,8 @@
4043
description['dtype_u'] = mesh
4144
description['dtype_f'] = rhs_imex_mesh
4245
description['collocation_class'] = collclass.CollGaussLobatto
43-
description['num_nodes'] = [2]
46+
description['num_nodes'] = [3]
47+
description['do_LU'] = False
4448
description['sweeper_class'] = imex_1st_order
4549
description['level_params'] = lparams
4650

@@ -62,15 +66,19 @@
6266

6367
uex = P.u_exact(Tend)
6468

65-
fig = plt.figure(figsize=(8,8))
66-
plt.pcolor(pparams['lambda_s'].imag, pparams['lambda_f'].imag, np.absolute(uend.values).T,vmin=1,vmax=1.01)
69+
fig = plt.figure(figsize=(4,4))
70+
#pcol = plt.pcolor(pparams['lambda_s'].imag, pparams['lambda_f'].imag, np.absolute(uend.values).T, vmin=0.99, vmax=1.01)
71+
pcol = plt.pcolor(pparams['lambda_s'].imag, pparams['lambda_f'].imag, np.absolute(uend.values).T, vmin=1.0, vmax=2.0)
6772
# plt.pcolor(np.imag(uend.values))
68-
plt.colorbar()
69-
plt.xlabel('$\Delta t \lambda_{slow}$', fontsize=18, labelpad=20)
73+
pcol.set_edgecolor('face')
74+
plt.plot([0, 4], [0, 4], color='w', linewidth=2.5)
75+
#plt.colorbar()
76+
plt.gca().set_xticks([0.0, 1.0, 2.0, 3.0])
77+
plt.xlabel('$\Delta t \lambda_{slow}$', fontsize=18, labelpad=0.0)
7078
plt.ylabel('$\Delta t \lambda_{fast}$', fontsize=18)
7179

72-
plt.show()
73-
80+
#plt.show()
81+
fig.savefig('sdc-fwsw-stability-K'+str(sparams['maxiter'])+'-M'+str(description['num_nodes'][0])+'.pdf', bbox_inches='tight')
7482
print('error at time %s: %s' %(Tend,np.linalg.norm(uex.values-uend.values,np.inf)/np.linalg.norm(uex.values,
7583
np.inf)))
7684

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from __future__ import division
2+
from pySDC.Hooks import hooks
3+
from pySDC.Stats import stats
4+
5+
import matplotlib.pyplot as plt
6+
import numpy as np
7+
8+
from matplotlib import pyplot as plt
9+
from mpl_toolkits.mplot3d import Axes3D
10+
from matplotlib import cm
11+
from matplotlib.ticker import LinearLocator, FormatStrFormatter
12+
13+
class plot_solution(hooks):
14+
15+
def __init__(self):
16+
"""
17+
Initialization of output
18+
"""
19+
super(plot_solution,self).__init__()
20+
21+
# add figure object for further use
22+
# self.fig = plt.figure(figsize=(18,6))
23+
#self.fig = plt.figure(figsize=(9,9))
24+
25+
26+
def dump_step(self,status):
27+
"""
28+
Overwrite standard dump per step
29+
30+
Args:
31+
status: status object per step
32+
"""
33+
super(plot_solution,self).dump_step(status)
34+
35+
if False:
36+
yplot = self.level.uend.values
37+
xx = self.level.prob.mesh
38+
self.fig.clear()
39+
plt.plot(xx, yplot[0,:])
40+
plt.axes().set_xlim(xmin = xx[0], xmax = np.max(xx))
41+
plt.axes().set_ylim(ymin=-0.1, ymax=1.1)
42+
#plt.axes().set_aspect('equal')
43+
plt.xlabel('x')
44+
plt.ylabel('p')
45+
#plt.tight_layout()
46+
plt.show(block=False)
47+
plt.pause(0.00001)
48+
49+
return None

examples/acoustic_1d_imex/ProblemClass.py

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@
1717
from pySDC.Problem import ptype
1818
from pySDC.datatype_classes.mesh import mesh, rhs_imex_mesh
1919

20-
# Sharpclaw imports
21-
from clawpack import pyclaw
22-
from clawpack import riemann
23-
24-
from getFDMatrix import getFDMatrix
20+
from buildWave1DMatrix import getWave1DMatrix, getWave1DAdvectionMatrix
2521

2622
def u_initial(x):
27-
return np.sin(2.0*np.pi*x)
23+
return np.sin(x)
2824
# return np.exp(-0.5*(x-0.5)**2/0.1**2)
2925

3026
class acoustic_1d_imex(ptype):
@@ -60,29 +56,13 @@ def __init__(self, cparams, dtype_u, dtype_f):
6056
# invoke super init, passing number of dofs, dtype_u and dtype_f
6157
super(acoustic_1d_imex,self).__init__(self.nvars,dtype_u,dtype_f)
6258

63-
riemann_solver = riemann.advection_1D # NOTE: This uses the FORTRAN kernels of clawpack
64-
self.solver = pyclaw.SharpClawSolver1D(riemann_solver)
65-
self.solver.weno_order = 5
66-
self.solver.time_integrator = 'Euler' # Remove later
67-
self.solver.kernel_language = 'Fortran'
68-
self.solver.bc_lower[0] = pyclaw.BC.periodic
69-
self.solver.bc_upper[0] = pyclaw.BC.periodic
70-
self.solver.cfl_max = 1.0
71-
assert self.solver.is_valid()
72-
73-
x = pyclaw.Dimension(0.0, 1.0, self.nvars[1], name='x')
74-
self.domain = pyclaw.Domain(x)
75-
self.state = pyclaw.State(self.domain, self.solver.num_eqn)
76-
self.mesh = self.state.grid.x.centers
59+
self.mesh = np.linspace(0.0, 1.0, self.nvars[1], endpoint=False)
7760
self.dx = self.mesh[1] - self.mesh[0]
78-
self.A = -self.cs*getFDMatrix(self.nvars[1], self.order_adv, self.dx)
79-
80-
self.state.problem_data['u'] = self.cadv
8161

82-
solution = pyclaw.Solution(self.state, self.domain)
83-
self.solver.setup(solution)
84-
85-
62+
self.Dx = -self.cadv*getWave1DAdvectionMatrix(self.nvars[1], self.dx, self.order_adv)
63+
self.Id, A = getWave1DMatrix(self.nvars[1], self.dx, ['periodic','periodic'], ['periodic','periodic'])
64+
self.A = -self.cs*A
65+
8666
def solve_system(self,rhs,factor,u0,t):
8767
"""
8868
Simple linear solver for (I-dtA)u = rhs
@@ -97,9 +77,7 @@ def solve_system(self,rhs,factor,u0,t):
9777
solution as mesh
9878
"""
9979

100-
M1 = sp.hstack( (sp.eye(self.nvars[1]), -factor*self.A) )
101-
M2 = sp.hstack( (-factor*self.A, sp.eye(self.nvars[1])) )
102-
M = sp.vstack( (M1, M2) )
80+
M = self.Id - factor*self.A
10381

10482
b = np.concatenate( (rhs.values[0,:], rhs.values[1,:]) )
10583

@@ -124,26 +102,12 @@ def __eval_fexpl(self,u,t):
124102
"""
125103

126104

105+
b = np.concatenate( (u.values[0,:], u.values[1,:]) )
106+
sol = self.Dx.dot(b)
107+
127108
fexpl = mesh(self.nvars)
109+
fexpl.values[0,:], fexpl.values[1,:] = np.split(sol, 2)
128110

129-
# Copy values of u into pyClaw state object
130-
self.state.q[0,:] = u.values[0,:]
131-
132-
# Evaluate right hand side
133-
tmp = self.solver.dqdt(self.state)
134-
fexpl.values[0,:] = tmp.reshape(self.nvars[1:])
135-
136-
# Copy values of u into pyClaw state object
137-
self.state.q[0,:] = u.values[1,:]
138-
139-
# Evaluate right hand side
140-
tmp = self.solver.dqdt(self.state)
141-
fexpl.values[1,:] = tmp.reshape(self.nvars[1:])
142-
143-
144-
# DEBUGGING
145-
# fexpl.values[0,:] = 0.0*self.mesh
146-
# fexpl.values[1,:] = 0.0*self.mesh
147111
return fexpl
148112

149113

@@ -159,9 +123,11 @@ def __eval_fimpl(self,u,t):
159123
implicit part of RHS
160124
"""
161125

126+
b = np.concatenate( (u.values[0,:], u.values[1,:]) )
127+
sol = self.A.dot(b)
128+
162129
fimpl = mesh(self.nvars,val=0)
163-
fimpl.values[0,:] = self.A.dot(u.values[1,:])
164-
fimpl.values[1,:] = self.A.dot(u.values[0,:])
130+
fimpl.values[0,:], fimpl.values[1,:] = np.split(sol, 2)
165131

166132
return fimpl
167133

@@ -194,9 +160,16 @@ def u_exact(self,t):
194160
exact solution
195161
"""
196162

163+
sigma_0 = 0.1
164+
k = 7.2*np.pi
165+
x_0 = 0.75
166+
x_1 = 0.25
167+
197168
me = mesh(self.nvars)
198-
me.values[0,:] = 0.5*u_initial(self.mesh - (self.cadv + self.cs)*t) + 0.5*u_initial(self.mesh - (self.cadv - self.cs)*t)
199-
me.values[1,:] = 0.5*u_initial(self.mesh - (self.cadv + self.cs)*t) - 0.5*u_initial(self.mesh - (self.cadv - self.cs)*t)
169+
#me.values[0,:] = 0.5*u_initial(self.mesh - (self.cadv + self.cs)*t) + 0.5*u_initial(self.mesh - (self.cadv - self.cs)*t)
170+
#me.values[1,:] = 0.5*u_initial(self.mesh - (self.cadv + self.cs)*t) - 0.5*u_initial(self.mesh - (self.cadv - self.cs)*t)
171+
me.values[0,:] = np.exp(-np.square(self.mesh-x_0-self.cs*t)/(sigma_0*sigma_0)) + np.exp(-np.square(self.mesh-x_1-self.cs*t)/(sigma_0*sigma_0))*np.cos(k*(self.mesh-self.cs*t)/sigma_0)
172+
me.values[1,:] = me.values[0,:]
200173
return me
201174

202175

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import numpy as np
2+
import scipy.sparse as sp
3+
import scipy.linalg as la
4+
5+
# Only for periodic BC because we have advection only in x direction
6+
def getHorizontalDx(N, dx, order):
7+
8+
if order==1:
9+
stencil = [-1.0, 1.0]
10+
zero_pos = 2
11+
coeff = 1.0
12+
13+
elif order==2:
14+
stencil = [1.0, -4.0, 3.0]
15+
coeff = 1.0/2.0
16+
zero_pos = 3
17+
18+
elif order==3:
19+
stencil = [1.0, -6.0, 3.0, 2.0]
20+
coeff = 1.0/6.0
21+
zero_pos = 3
22+
23+
elif order==4:
24+
stencil = [-5.0, 30.0, -90.0, 50.0, 15.0]
25+
coeff = 1.0/60.0
26+
zero_pos = 4
27+
28+
elif order==5:
29+
stencil = [3.0, -20.0, 60.0, -120.0, 65.0, 12.0]
30+
coeff = 1.0/60.0
31+
zero_pos = 5
32+
else:
33+
print "Order "+str(order)+" not implemented."
34+
35+
first_col = np.zeros(N)
36+
37+
# Because we need to specific first column (not row) in circulant, flip stencil array
38+
first_col[0:np.size(stencil)] = np.flipud(stencil)
39+
40+
# Circulant shift of coefficient column so that entry number zero_pos becomes first entry
41+
first_col = np.roll(first_col, -np.size(stencil)+zero_pos, axis=0)
42+
43+
return sp.csc_matrix( coeff*(1.0/dx)*la.circulant(first_col) )
44+
45+
def getMatrix(N, dx, bc_left, bc_right):
46+
stencil = [1.0, -8.0, 0.0, 8.0, -1.0]
47+
range = [ -2, -1, 0, 1, 2]
48+
A = sp.diags(stencil, range, shape=(N,N))
49+
A = sp.lil_matrix(A)
50+
51+
assert bc_left in ['periodic','neumann','dirichlet'], "Unknown type of BC"
52+
53+
if bc_left in ['periodic']:
54+
assert bc_right in ['periodic'], "Periodic BC can only be selected for both sides simultaneously"
55+
56+
if bc_left in ['periodic']:
57+
A[0,N-2] = stencil[0]
58+
A[0,N-1] = stencil[1]
59+
A[1,N-1] = stencil[0]
60+
61+
if bc_right in ['periodic']:
62+
A[N-2,0] = stencil[4]
63+
A[N-1,0] = stencil[3]
64+
A[N-1,1] = stencil[4]
65+
66+
if bc_left in ['neumann']:
67+
A[0,:] = np.zeros(N)
68+
A[0,0] = -8.0
69+
A[0,1] = 8.0
70+
A[1,0] = -8.0 + 4.0/3.0
71+
A[1,1] = -1.0/3.0
72+
73+
if bc_right in ['neumann']:
74+
A[N-1,:] = np.zeros(N)
75+
A[N-2,N-1] = 8.0 - 4.0/3.0
76+
A[N-2,N-2] = 1.0/3.0
77+
A[N-1,N-1] = 8.0
78+
A[N-1,N-2] = -8.0
79+
80+
if bc_left in ['dirichlet']:
81+
A[0,:] = np.zeros(N)
82+
A[0,1] = 6.0
83+
84+
if bc_right in ['dirichlet']:
85+
A[N-1,:] = np.zeros(N)
86+
A[N-1,N-2] = -6.0
87+
88+
A = 1.0/(12.0*dx)*A
89+
90+
return sp.csc_matrix(A)
91+
92+
def getBCLeft(value, N, dx, type):
93+
94+
assert type in ['periodic','neumann','dirichlet'], "Unknown type of BC"
95+
96+
b = np.zeros(N)
97+
if type in ['dirichlet']:
98+
b[0] = -6.0*value
99+
b[1] = 1.0*value
100+
101+
if type in ['neumann']:
102+
b[0] = 4.0*dx*value
103+
b[1] = -(2.0/3.0)*dx*value
104+
105+
return (1.0/(12.0*dx))*b
106+
107+
def getBCRight(value, N, dx, type):
108+
109+
assert type in ['periodic','neumann','dirichlet'], "Unknown type of BC"
110+
111+
b = np.zeros(N)
112+
if type in ['dirichlet']:
113+
b[N-2] = -1.0*value
114+
b[N-1] = 6.0*value
115+
116+
if type in ['neumann']:
117+
b[N-2] = -(2.0/3.0)*dx*value
118+
b[N-1] = 4.0*dx*value
119+
120+
return (1.0/(12.0*dx))*b
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import sys
2+
sys.path.append('../')
3+
import numpy as np
4+
import scipy.sparse as sp
5+
from buildFDMatrix import getMatrix, getHorizontalDx, getBCLeft, getBCRight
6+
7+
def getWave1DMatrix(N, dx, bc_left, bc_right):
8+
9+
Id = sp.eye(2*N)
10+
11+
D_u = getMatrix(N, dx, bc_left[0], bc_right[0])
12+
D_p = getMatrix(N, dx, bc_left[1], bc_right[1])
13+
Zero = np.zeros((N,N))
14+
M1 = sp.hstack((Zero, D_p), format="csc")
15+
M2 = sp.hstack((D_u, Zero), format="csc")
16+
M = sp.vstack((M1, M2), format="csc")
17+
return sp.csc_matrix(Id), sp.csc_matrix(M)
18+
19+
def getWave1DAdvectionMatrix(N, dx, order):
20+
Dx = getHorizontalDx(N, dx, order)
21+
Zero = np.zeros((N,N))
22+
M1 = sp.hstack((Dx, Zero), format="csc")
23+
M2 = sp.hstack((Zero, Dx), format="csc")
24+
M = sp.vstack((M1, M2), format="csc")
25+
return sp.csc_matrix(M)
26+
27+
def getWaveBCLeft(value, N, dx, bc_left):
28+
bu = getBCLeft(value[0], N, dx, bc_left[0])
29+
bp = getBCLeft(value[1], N, dx, bc_left[1])
30+
return np.concatenate((bp, bu))
31+
32+
def getWaveBCRight(value, N, dx, bc_right):
33+
bu = getBCRight(value[0], N, dx, bc_right[0])
34+
bp = getBCRight(value[1], N, dx, bc_right[1])
35+
return np.concatenate((bp, bu))

0 commit comments

Comments
 (0)