Skip to content

Commit d240293

Browse files
committed
Merge pull request #48 from danielru/fwsw_sdc_acoustic1d
Iteration and convergence plots for fwsw SDC
2 parents d5e5260 + 998fac3 commit d240293

File tree

7 files changed

+472
-98
lines changed

7 files changed

+472
-98
lines changed

examples/acoustic_1d_imex/HookClass.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ def __init__(self):
2222
# self.fig = plt.figure(figsize=(18,6))
2323
#self.fig = plt.figure(figsize=(9,9))
2424

25+
def dump_sweep(self,status):
26+
return None
2527

2628
def dump_step(self,status):
2729
"""
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
r"""
2+
One-dimensional IMEX acoustic-advection
3+
=========================
4+
5+
Integrate the linear 1D acoustic-advection problem:
6+
7+
.. math::
8+
u_t + U u_x + c p_x & = 0 \\
9+
p_t + U p_x + c u_x & = 0.
10+
11+
"""
12+
13+
import numpy as np
14+
import scipy.sparse as sp
15+
import scipy.sparse.linalg as LA
16+
17+
from pySDC.Problem import ptype
18+
from pySDC.datatype_classes.mesh import mesh, rhs_imex_mesh
19+
20+
from buildWave1DMatrix import getWave1DMatrix, getWave1DAdvectionMatrix
21+
22+
def u_initial(x, k):
23+
return np.sin(k*2.0*np.pi*x)
24+
25+
class acoustic_1d_imex(ptype):
26+
"""
27+
Example implementing the forced 1D heat equation with Dirichlet-0 BC in [0,1]
28+
29+
Attributes:
30+
solver: Sharpclaw solver
31+
state: Sharclaw state
32+
domain: Sharpclaw domain
33+
"""
34+
35+
def __init__(self, cparams, dtype_u, dtype_f):
36+
"""
37+
Initialization routine
38+
39+
Args:
40+
cparams: custom parameters for the example
41+
dtype_u: particle data type (will be passed parent class)
42+
dtype_f: acceleration data type (will be passed parent class)
43+
"""
44+
45+
# these parameters will be used later, so assert their existence
46+
assert 'nvars' in cparams
47+
assert 'cs' in cparams
48+
assert 'cadv' in cparams
49+
assert 'order_adv' in cparams
50+
assert 'waveno' in cparams
51+
52+
# add parameters as attributes for further reference
53+
for k,v in cparams.items():
54+
setattr(self,k,v)
55+
56+
# invoke super init, passing number of dofs, dtype_u and dtype_f
57+
super(acoustic_1d_imex,self).__init__(self.nvars,dtype_u,dtype_f)
58+
59+
self.mesh = np.linspace(0.0, 1.0, self.nvars[1], endpoint=False)
60+
self.dx = self.mesh[1] - self.mesh[0]
61+
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+
66+
def solve_system(self,rhs,factor,u0,t):
67+
"""
68+
Simple linear solver for (I-dtA)u = rhs
69+
70+
Args:
71+
rhs: right-hand side for the nonlinear system
72+
factor: abbrev. for the node-to-node stepsize (or any other factor required)
73+
u0: initial guess for the iterative solver (not used here so far)
74+
t: current time (e.g. for time-dependent BCs)
75+
76+
Returns:
77+
solution as mesh
78+
"""
79+
80+
M = self.Id - factor*self.A
81+
82+
b = np.concatenate( (rhs.values[0,:], rhs.values[1,:]) )
83+
84+
sol = LA.spsolve(M, b)
85+
86+
me = mesh(self.nvars)
87+
me.values[0,:], me.values[1,:] = np.split(sol, 2)
88+
89+
return me
90+
91+
92+
def __eval_fexpl(self,u,t):
93+
"""
94+
Helper routine to evaluate the explicit part of the RHS
95+
96+
Args:
97+
u: current values (not used here)
98+
t: current time
99+
100+
Returns:
101+
explicit part of RHS
102+
"""
103+
104+
105+
b = np.concatenate( (u.values[0,:], u.values[1,:]) )
106+
sol = self.Dx.dot(b)
107+
108+
fexpl = mesh(self.nvars)
109+
fexpl.values[0,:], fexpl.values[1,:] = np.split(sol, 2)
110+
111+
return fexpl
112+
113+
114+
def __eval_fimpl(self,u,t):
115+
"""
116+
Helper routine to evaluate the implicit part of the RHS
117+
118+
Args:
119+
u: current values
120+
t: current time (not used here)
121+
122+
Returns:
123+
implicit part of RHS
124+
"""
125+
126+
b = np.concatenate( (u.values[0,:], u.values[1,:]) )
127+
sol = self.A.dot(b)
128+
129+
fimpl = mesh(self.nvars,val=0)
130+
fimpl.values[0,:], fimpl.values[1,:] = np.split(sol, 2)
131+
132+
return fimpl
133+
134+
135+
def eval_f(self,u,t):
136+
"""
137+
Routine to evaluate both parts of the RHS
138+
139+
Args:
140+
u: current values
141+
t: current time
142+
143+
Returns:
144+
the RHS divided into two parts
145+
"""
146+
147+
f = rhs_imex_mesh(self.nvars)
148+
f.impl = self.__eval_fimpl(u,t)
149+
f.expl = self.__eval_fexpl(u,t)
150+
return f
151+
152+
def u_exact(self,t):
153+
"""
154+
Routine to compute the exact solution at time t
155+
156+
Args:
157+
t: current time
158+
159+
Returns:
160+
exact solution
161+
"""
162+
163+
me = mesh(self.nvars)
164+
me.values[0,:] = 0.5*u_initial( self.mesh - (self.cadv + self.cs)*t , self.waveno) - 0.5*u_initial( self.mesh - (self.cadv - self.cs)*t , self.waveno)
165+
me.values[1,:] = 0.5*u_initial( self.mesh - (self.cadv + self.cs)*t , self.waveno) + 0.5*u_initial( self.mesh - (self.cadv - self.cs)*t , self.waveno)
166+
return me
167+
168+

examples/acoustic_1d_imex/buildFDMatrix.py

Lines changed: 104 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def getHorizontalDx(N, dx, order):
3030
coeff = 1.0/60.0
3131
zero_pos = 5
3232
else:
33-
print "Order "+str(order)+" not implemented."
33+
print "Order "+order+" not implemented."
3434

3535
first_col = np.zeros(N)
3636

@@ -42,79 +42,143 @@ def getHorizontalDx(N, dx, order):
4242

4343
return sp.csc_matrix( coeff*(1.0/dx)*la.circulant(first_col) )
4444

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)
45+
def getMatrix(N, dx, bc_left, bc_right, order):
5046

5147
assert bc_left in ['periodic','neumann','dirichlet'], "Unknown type of BC"
48+
49+
if order==2:
50+
stencil = [-1.0, 0.0, 1.0]
51+
range = [-1, 0, 1]
52+
coeff = 1.0/2.0
53+
elif order==4:
54+
stencil = [1.0, -8.0, 0.0, 8.0, -1.0]
55+
range = [ -2, -1, 0, 1, 2]
56+
coeff = 1.0/12.0
57+
58+
A = sp.diags(stencil, range, shape=(N,N))
59+
A = sp.lil_matrix(A)
5260

61+
#
62+
# Periodic boundary conditions
63+
#
5364
if bc_left in ['periodic']:
5465
assert bc_right in ['periodic'], "Periodic BC can only be selected for both sides simultaneously"
5566

5667
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]
68+
if order==2:
69+
A[0,N-1] = stencil[0]
6070

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]
71+
elif order==4:
72+
A[0,N-2] = stencil[0]
73+
A[0,N-1] = stencil[1]
74+
A[1,N-1] = stencil[0]
6575

76+
if bc_right in ['periodic']:
77+
if order==2:
78+
A[N-1,0] = stencil[2]
79+
elif order==4:
80+
A[N-2,0] = stencil[4]
81+
A[N-1,0] = stencil[3]
82+
A[N-1,1] = stencil[4]
83+
84+
#
85+
# Neumann boundary conditions
86+
#
6687
if bc_left in ['neumann']:
6788
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
89+
if order==2:
90+
A[0,0] = -4.0/3.0
91+
A[0,1] = 4.0/3.0
92+
elif order==4:
93+
A[0,0] = -8.0
94+
A[0,1] = 8.0
95+
A[1,0] = -8.0 + 4.0/3.0
96+
A[1,1] = -1.0/3.0
7297

7398
if bc_right in ['neumann']:
7499
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-
100+
if order==2:
101+
A[N-1,N-2] = -4.0/3.0
102+
A[N-1,N-1] = 4.0/3.0
103+
elif order==4:
104+
A[N-2,N-1] = 8.0 - 4.0/3.0
105+
A[N-2,N-2] = 1.0/3.0
106+
A[N-1,N-1] = 8.0
107+
A[N-1,N-2] = -8.0
108+
109+
#
110+
# Dirichlet boundary conditions
111+
#
80112
if bc_left in ['dirichlet']:
81-
A[0,:] = np.zeros(N)
82-
A[0,1] = 6.0
113+
# For order==2, nothing to do here
114+
if order==4:
115+
A[0,:] = np.zeros(N)
116+
A[0,1] = 6.0
83117

84118
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
119+
# For order==2, nothing to do here
120+
if order==4:
121+
A[N-1,:] = np.zeros(N)
122+
A[N-1,N-2] = -6.0
89123

124+
125+
A = coeff*(1.0/dx)*A
90126
return sp.csc_matrix(A)
91127

92-
def getBCLeft(value, N, dx, type):
128+
#
129+
#
130+
#
131+
def getBCLeft(value, N, dx, type, order):
93132

94133
assert type in ['periodic','neumann','dirichlet'], "Unknown type of BC"
95134

135+
if order==2:
136+
coeff = 1.0/2.0
137+
elif order==4:
138+
coeff = 1.0/12.0
139+
96140
b = np.zeros(N)
97141
if type in ['dirichlet']:
98-
b[0] = -6.0*value
99-
b[1] = 1.0*value
142+
if order==2:
143+
b[0] = -value;
144+
elif order==4:
145+
b[0] = -6.0*value
146+
b[1] = 1.0*value
100147

101148
if type in ['neumann']:
102-
b[0] = 4.0*dx*value
103-
b[1] = -(2.0/3.0)*dx*value
149+
if order==2:
150+
b[0] = (2.0/3.0)*dx*value
151+
elif order==4:
152+
b[0] = 4.0*dx*value
153+
b[1] = -(2.0/3.0)*dx*value
104154

105-
return (1.0/(12.0*dx))*b
155+
return coeff*(1.0/dx)*b
106156

107-
def getBCRight(value, N, dx, type):
157+
#
158+
#
159+
#
160+
def getBCRight(value, N, dx, type, order):
108161

109162
assert type in ['periodic','neumann','dirichlet'], "Unknown type of BC"
110163

164+
if order==2:
165+
coeff = 1.0/2.0
166+
elif order==4:
167+
coeff = 1.0/12.0
168+
111169
b = np.zeros(N)
112170
if type in ['dirichlet']:
113-
b[N-2] = -1.0*value
114-
b[N-1] = 6.0*value
171+
if order==2:
172+
b[N-1] = value
173+
elif order==4:
174+
b[N-2] = -1.0*value
175+
b[N-1] = 6.0*value
115176

116177
if type in ['neumann']:
117-
b[N-2] = -(2.0/3.0)*dx*value
118-
b[N-1] = 4.0*dx*value
178+
if order==2:
179+
b[N-1] = (2.0/3.0)*dx*value
180+
elif order==4:
181+
b[N-2] = -(2.0/3.0)*dx*value
182+
b[N-1] = 4.0*dx*value
119183

120-
return (1.0/(12.0*dx))*b
184+
return coeff*(1.0/dx)*b

0 commit comments

Comments
 (0)