Skip to content

Commit 884b57f

Browse files
committed
Merge pull request #50 from danielru/fwsw_boussinesq
Boussinesq
2 parents c212658 + 7fc052d commit 884b57f

File tree

4 files changed

+260
-8
lines changed

4 files changed

+260
-8
lines changed

examples/boussinesq_2d_imex/HookClass.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ def __init__(self):
2020

2121
# add figure object for further use
2222
# self.fig = plt.figure(figsize=(18,6))
23-
self.fig = plt.figure(figsize=(15,5))
24-
self.counter = 0
23+
#self.fig = plt.figure(figsize=(15,5))
24+
#self.counter = 0
25+
26+
def dump_sweep(self,status):
27+
pass
2528

2629
def dump_step(self,status):
2730
"""

examples/boussinesq_2d_imex/ProblemClass.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def solve_system(self,rhs,factor,u0,t):
106106
sol, info = LA.gmres( self.Id - factor*self.M, b, x0=u0.values.flatten(), tol=self.gmres_tol, restart=self.gmres_restart, maxiter=self.gmres_maxiter, callback=cb)
107107
# If this is a dummy call with factor==0.0, do not log because it should not be counted as a solver call
108108
if factor!=0.0:
109-
print "Number of GMRES iterations: %3i --- Final residual: %6.3e" % ( cb.getcounter(), cb.getresidual() )
109+
print "SDC: Number of GMRES iterations: %3i --- Final residual: %6.3e" % ( cb.getcounter(), cb.getresidual() )
110110
self.logger.add(cb.getcounter())
111111
me = mesh(self.nvars)
112112
me.values = unflatten(sol, 4, self.N[0], self.N[1])
@@ -197,8 +197,3 @@ def u_exact(self,t):
197197
me.values[2,:,:] = dtheta*np.sin( np.pi*self.zz/H )/( 1.0 + np.square(self.xx - x_c)/(a*a))
198198
me.values[3,:,:] = 0.0*self.xx
199199
return me
200-
201-
def report_log(self):
202-
print "Number of calls to implicit solver: %5i" % self.logger.solver_calls
203-
print "Total number of iterations: %5i" % self.logger.iterations
204-
print "Average number of iterations per call: %6.3f" % (float(self.logger.iterations)/float(self.logger.solver_calls))
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
2+
from pySDC import CollocationClasses as collclass
3+
4+
import numpy as np
5+
6+
from ProblemClass import boussinesq_2d_imex
7+
from examples.boussinesq_2d_imex.TransferClass import mesh_to_mesh_2d
8+
from examples.boussinesq_2d_imex.HookClass import plot_solution
9+
10+
from pySDC.datatype_classes.mesh import mesh, rhs_imex_mesh
11+
from pySDC.sweeper_classes.imex_1st_order import imex_1st_order
12+
import pySDC.PFASST_stepwise as mp
13+
from pySDC import Log
14+
from pySDC.Stats import grep_stats, sort_stats
15+
16+
from matplotlib import pyplot as plt
17+
from mpl_toolkits.mplot3d import Axes3D
18+
from matplotlib import cm
19+
from matplotlib.ticker import LinearLocator, FormatStrFormatter
20+
from pylab import rcParams
21+
22+
from unflatten import unflatten
23+
24+
from standard_integrators import dirk
25+
26+
if __name__ == "__main__":
27+
28+
# set global logger (remove this if you do not want the output at all)
29+
logger = Log.setup_custom_logger('root')
30+
31+
num_procs = 1
32+
33+
# This comes as read-in for the level class
34+
lparams = {}
35+
lparams['restol'] = 1E-15
36+
37+
swparams = {}
38+
swparams['collocation_class'] = collclass.CollGaussLobatto
39+
swparams['num_nodes'] = 3
40+
swparams['do_LU'] = False
41+
42+
sparams = {}
43+
sparams['maxiter'] = 3
44+
45+
dirk_order = 2
46+
47+
# setup parameters "in time"
48+
t0 = 0
49+
Tend = 3000
50+
Nsteps = 500
51+
#Tend = 30
52+
#Nsteps = 5
53+
dt = Tend/float(Nsteps)
54+
55+
# This comes as read-in for the problem class
56+
pparams = {}
57+
pparams['nvars'] = [(4,300,20)]
58+
#pparams['nvars'] = [(4,150,10)]
59+
pparams['u_adv'] = 0.02
60+
pparams['c_s'] = 0.3
61+
pparams['Nfreq'] = 0.01
62+
pparams['x_bounds'] = [(-150.0, 150.0)]
63+
pparams['z_bounds'] = [( 0.0, 10.0)]
64+
pparams['order'] = [4] # [fine_level, coarse_level]
65+
pparams['order_upw'] = [5]
66+
pparams['gmres_maxiter'] = [500]
67+
pparams['gmres_restart'] = [10]
68+
pparams['gmres_tol'] = [1e-6]
69+
70+
# This comes as read-in for the transfer operations
71+
tparams = {}
72+
tparams['finter'] = False
73+
74+
# Fill description dictionary for easy hierarchy creation
75+
description = {}
76+
description['problem_class'] = boussinesq_2d_imex
77+
description['problem_params'] = pparams
78+
description['dtype_u'] = mesh
79+
description['dtype_f'] = rhs_imex_mesh
80+
description['sweeper_params'] = swparams
81+
description['sweeper_class'] = imex_1st_order
82+
description['level_params'] = lparams
83+
description['hook_class'] = plot_solution
84+
85+
# quickly generate block of steps
86+
MS = mp.generate_steps(num_procs,sparams,description)
87+
88+
# get initial values on finest level
89+
P = MS[0].levels[0].prob
90+
uinit = P.u_exact(t0)
91+
92+
cfl_advection = pparams['u_adv']*dt/P.h[0]
93+
cfl_acoustic_hor = pparams['c_s']*dt/P.h[0]
94+
cfl_acoustic_ver = pparams['c_s']*dt/P.h[1]
95+
print ("CFL number of advection: %4.2f" % cfl_advection)
96+
print ("CFL number of acoustics (horizontal): %4.2f" % cfl_acoustic_hor)
97+
print ("CFL number of acoustics (vertical): %4.2f" % cfl_acoustic_ver)
98+
99+
dirk = dirk(P, dirk_order)
100+
u0 = uinit.values.flatten()
101+
102+
for i in range(0,Nsteps):
103+
u0 = dirk.timestep(u0, dt)
104+
105+
# call main function to get things done...
106+
uend,stats = mp.run_pfasst(MS,u0=uinit,t0=t0,dt=dt,Tend=Tend)
107+
108+
u0 = unflatten(u0, 4, P.N[0], P.N[1])
109+
110+
fs = 8
111+
rcParams['figure.figsize'] = 5.0, 2.5
112+
fig = plt.figure()
113+
114+
plt.plot(P.xx[:,5], uend.values[2,:,5], '-', color='b', label='SDC')
115+
plt.plot(P.xx[:,5], u0[2,:,5], '+', color='g', markevery=5, markersize=fs-2, label='DIRK')
116+
plt.legend(loc='lower left', fontsize=fs, prop={'size':fs})
117+
plt.yticks(fontsize=fs)
118+
plt.xticks(fontsize=fs)
119+
plt.xlabel('x', fontsize=fs, labelpad=0)
120+
plt.ylabel('Bouyancy', fontsize=fs, labelpad=1)
121+
#plt.show()
122+
plt.savefig('boussinesq.pdf', bbox_inches='tight')
123+
124+
print " #### Logging report for DIRK #### "
125+
print "Number of calls to implicit solver: %5i" % dirk.logger.solver_calls
126+
print "Total number of GMRES iterations: %5i" % dirk.logger.iterations
127+
print "Average number of iterations per call: %6.3f" % (float(dirk.logger.iterations)/float(dirk.logger.solver_calls))
128+
129+
print " #### Logging report for SDC #### "
130+
print "Number of calls to implicit solver: %5i" % P.logger.solver_calls
131+
print "Total number of GMRES iterations: %5i" % P.logger.iterations
132+
print "Average number of iterations per call: %6.3f" % (float(P.logger.iterations)/float(P.logger.solver_calls))
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import numpy as np
2+
import math
3+
import scipy.sparse.linalg as LA
4+
import scipy.sparse as sp
5+
from ProblemClass import Callback, logging, boussinesq_2d_imex
6+
7+
#
8+
# A diagonally implicit Runge-Kutta method of order 2, 3 or 4
9+
#
10+
class dirk:
11+
12+
def __init__(self, problem, order):
13+
14+
assert isinstance(problem, boussinesq_2d_imex), "problem is wrong type of object"
15+
self.Ndof = np.shape(problem.M)[0]
16+
self.order = order
17+
self.logger = logging()
18+
self.problem = problem
19+
20+
assert self.order in [2,22,3,4], 'Order must be 2,22,3,4'
21+
22+
if (self.order==2):
23+
self.nstages = 1
24+
self.A = np.zeros((1,1))
25+
self.A[0,0] = 0.5
26+
self.tau = [0.5]
27+
self.b = [1.0]
28+
29+
if (self.order==22):
30+
self.nstages = 2
31+
self.A = np.zeros((2,2))
32+
self.A[0,0] = 1.0/3.0
33+
self.A[1,0] = 1.0/2.0
34+
self.A[1,1] = 1.0/2.0
35+
36+
self.tau = np.zeros(2)
37+
self.tau[0] = 1.0/3.0
38+
self.tau[1] = 1.0
39+
40+
self.b = np.zeros(2)
41+
self.b[0] = 3.0/4.0
42+
self.b[1] = 1.0/4.0
43+
44+
45+
if (self.order==3):
46+
self.nstages = 2
47+
self.A = np.zeros((2,2))
48+
self.A[0,0] = 0.5 + 1.0/( 2.0*math.sqrt(3.0) )
49+
self.A[1,0] = -1.0/math.sqrt(3.0)
50+
self.A[1,1] = self.A[0,0]
51+
52+
self.tau = np.zeros(2)
53+
self.tau[0] = 0.5 + 1.0/( 2.0*math.sqrt(3.0) )
54+
self.tau[1] = 0.5 - 1.0/( 2.0*math.sqrt(3.0) )
55+
56+
self.b = np.zeros(2)
57+
self.b[0] = 0.5
58+
self.b[1] = 0.5
59+
60+
if (self.order==4):
61+
self.nstages = 3
62+
alpha = 2.0*math.cos(math.pi/18.0)/math.sqrt(3.0)
63+
64+
self.A = np.zeros((3,3))
65+
self.A[0,0] = (1.0 + alpha)/2.0
66+
self.A[1,0] = -alpha/2.0
67+
self.A[1,1] = self.A[0,0]
68+
self.A[2,0] = (1.0 + alpha)
69+
self.A[2,1] = -(1.0 + 2.0*alpha)
70+
self.A[2,2] = self.A[0,0]
71+
72+
self.tau = np.zeros(3)
73+
self.tau[0] = (1.0 + alpha)/2.0
74+
self.tau[1] = 1.0/2.0
75+
self.tau[2] = (1.0 - alpha)/2.0
76+
77+
self.b = np.zeros(3)
78+
self.b[0] = 1.0/(6.0*alpha*alpha)
79+
self.b[1] = 1.0 - 1.0/(3.0*alpha*alpha)
80+
self.b[2] = 1.0/(6.0*alpha*alpha)
81+
82+
self.stages = np.zeros((self.nstages,self.Ndof))
83+
84+
def timestep(self, u0, dt):
85+
86+
uend = u0
87+
for i in range(0,self.nstages):
88+
89+
b = u0
90+
91+
# Compute right hand side for this stage's implicit step
92+
for j in range(0,i):
93+
b = b + self.A[i,j]*dt*self.f(self.stages[j,:])
94+
95+
# Implicit solve for current stage
96+
#if i==0:
97+
self.stages[i,:] = self.f_solve( b, dt*self.A[i,i] , u0 )
98+
#else:
99+
# self.stages[i,:] = self.f_solve( b, dt*self.A[i,i] , self.stages[i-1,:] )
100+
101+
# Add contribution of current stage to final value
102+
uend = uend + self.b[i]*dt*self.f(self.stages[i,:])
103+
104+
return uend
105+
106+
#
107+
# Returns f(u) = c*u
108+
#
109+
def f(self,u):
110+
return self.problem.D_upwind.dot(u)+self.problem.M.dot(u)
111+
112+
113+
#
114+
# Solves (Id - alpha*c)*u = b for u
115+
#
116+
def f_solve(self, b, alpha, u0):
117+
cb = Callback()
118+
sol, info = LA.gmres( self.problem.Id - alpha*(self.problem.D_upwind + self.problem.M), b, x0=u0, tol=self.problem.gmres_tol, restart=self.problem.gmres_restart, maxiter=self.problem.gmres_maxiter, callback=cb)
119+
if alpha!=0.0:
120+
print "DIRK: Number of GMRES iterations: %3i --- Final residual: %6.3e" % ( cb.getcounter(), cb.getresidual() )
121+
self.logger.add(cb.getcounter())
122+
return sol

0 commit comments

Comments
 (0)