Skip to content

Commit 8981101

Browse files
committed
fixed propagator (now for real), added test, bugfixes
1 parent 678dea1 commit 8981101

File tree

6 files changed

+136
-50
lines changed

6 files changed

+136
-50
lines changed

pySDC/implementations/transfer_classes/TransferMesh_NoCoarse.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import scipy.sparse as sp
44

55
from pySDC.implementations.datatype_classes.mesh import mesh, rhs_imex_mesh
6+
from pySDC.implementations.datatype_classes.complex_mesh import mesh as cmesh
67
from pySDC.core.SpaceTransfer import space_transfer
78
from pySDC.core.Errors import TransferError
89

@@ -43,6 +44,8 @@ def restrict(self, F):
4344
"""
4445
if isinstance(F, mesh):
4546
G = mesh(F)
47+
elif isinstance(F, cmesh):
48+
G = cmesh(F)
4649
elif isinstance(F, rhs_imex_mesh):
4750
G = rhs_imex_mesh(F)
4851
else:
@@ -58,6 +61,8 @@ def prolong(self, G):
5861
"""
5962
if isinstance(G, mesh):
6063
F = mesh(G)
64+
elif isinstance(G, cmesh):
65+
F = cmesh(G)
6166
elif isinstance(G, rhs_imex_mesh):
6267
F = rhs_imex_mesh(G)
6368
else:

pySDC/projects/matrixPFASST/allinclusive_matrix_nonMPI.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ def __init__(self, num_procs, controller_params, description):
8585

8686
Ac = prob_c.A.todense()
8787
Qdc = self.MS[0].levels[1].sweep.QI[1:, 1:]
88-
8988
nnodesc = self.MS[0].levels[1].sweep.coll.num_nodes
9089
Nc = np.zeros((nnodesc, nnodesc))
9190
Nc[:, -1] = 1
@@ -181,15 +180,16 @@ def build_propagation_matrix(self, niter):
181180
for k in range(1, self.MS[0].levels[0].params.nsweeps):
182181
precond_smoother += np.linalg.matrix_power(iter_mat_smoother, k).dot(Pinv)
183182
iter_mat_smoother = np.linalg.matrix_power(iter_mat_smoother, self.MS[0].levels[0].params.nsweeps)
184-
iter_mat = iter_mat_smoother
185-
precond = precond_smoother
186183

187184
# add coarse-grid correction (single sweep, though!)
188185
if self.nlevels > 1:
189186
precond_cgc = self.Tcf.dot(np.linalg.inv(self.Pc)).dot(self.Tfc)
190187
iter_mat_cgc = np.eye(self.nsteps * self.nnodes * self.nspace) - precond_cgc.dot(self.C)
191-
iter_mat = iter_mat.dot(iter_mat_cgc)
192-
precond += precond_cgc - precond_smoother.dot(self.C).dot(precond_cgc)
188+
iter_mat = iter_mat_smoother.dot(iter_mat_cgc)
189+
precond = precond_smoother + precond_cgc - precond_smoother.dot(self.C).dot(precond_cgc)
190+
else:
191+
iter_mat = iter_mat_smoother
192+
precond = precond_smoother
193193

194194
# form span and reduce matrices and add to operator
195195
Tspread = np.kron(np.concatenate([[1] * (self.nsteps * self.nnodes)]), np.eye(self.nspace)).T

pySDC/projects/matrixPFASST/compare_to_matrixbased.py

Lines changed: 92 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1+
import numpy as np
2+
13
from pySDC.implementations.problem_classes.HeatEquation_1D_FD import heat1d
24
from pySDC.implementations.problem_classes.AdvectionEquation_1D_FD import advection1d
5+
from pySDC.implementations.problem_classes.TestEquation_0D import testequation0d
36
from pySDC.implementations.datatype_classes.mesh import mesh
7+
from pySDC.implementations.datatype_classes.complex_mesh import mesh as cmesh
48
from pySDC.implementations.collocation_classes.gauss_radau_right import CollGaussRadau_Right
59
from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
610
from pySDC.implementations.transfer_classes.TransferMesh import mesh_to_mesh
11+
from pySDC.implementations.transfer_classes.TransferMesh_NoCoarse import mesh_to_mesh as mesh_to_mesh_nocoarse
712
from pySDC.implementations.controller_classes.allinclusive_multigrid_nonMPI import allinclusive_multigrid_nonMPI
813
from pySDC.projects.matrixPFASST.allinclusive_matrix_nonMPI import allinclusive_matrix_nonMPI
914

1015
from pySDC.helpers.stats_helper import filter_stats, sort_stats
1116

1217

13-
def diffusion_setup(mu=0.0):
18+
def diffusion_setup(par=0.0):
1419
"""
1520
Setup routine for advection test
1621
1722
Args:
18-
mu (float): parameter for controlling stiffness
23+
par (float): parameter for controlling stiffness
1924
"""
2025
# initialize level parameters
2126
level_params = dict()
@@ -32,7 +37,7 @@ def diffusion_setup(mu=0.0):
3237

3338
# initialize problem parameters
3439
problem_params = dict()
35-
problem_params['nu'] = mu # diffusion coefficient
40+
problem_params['nu'] = par # diffusion coefficient
3641
problem_params['freq'] = 4 # frequency for the test value
3742
problem_params['nvars'] = [127, 63] # number of degrees of freedom for each level
3843

@@ -66,12 +71,12 @@ def diffusion_setup(mu=0.0):
6671
return description, controller_params
6772

6873

69-
def advection_setup(mu=0.0):
74+
def advection_setup(par=0.0):
7075
"""
7176
Setup routine for advection test
7277
7378
Args:
74-
mu (float): parameter for controlling stiffness
79+
par (float): parameter for controlling stiffness
7580
"""
7681
# initialize level parameters
7782
level_params = dict()
@@ -88,7 +93,7 @@ def advection_setup(mu=0.0):
8893

8994
# initialize problem parameters
9095
problem_params = dict()
91-
problem_params['c'] = mu
96+
problem_params['c'] = par
9297
problem_params['freq'] = 4 # frequency for the test value
9398
problem_params['nvars'] = [128, 64] # number of degrees of freedom for each level
9499
problem_params['order'] = 2
@@ -125,13 +130,80 @@ def advection_setup(mu=0.0):
125130
return description, controller_params
126131

127132

128-
def compare_controllers(type=None, mu=0.0, f=None):
133+
def testequation_setup():
134+
"""
135+
Setup routine for the test equation
136+
137+
Args:
138+
par (float): parameter for controlling stiffness
139+
"""
140+
# initialize level parameters
141+
level_params = dict()
142+
level_params['restol'] = 1E-08
143+
level_params['dt'] = 0.25
144+
level_params['nsweeps'] = [3, 1]
145+
146+
# initialize sweeper parameters
147+
sweeper_params = dict()
148+
sweeper_params['collocation_class'] = CollGaussRadau_Right
149+
sweeper_params['num_nodes'] = [3, 2]
150+
sweeper_params['QI'] = 'LU'
151+
sweeper_params['spread'] = True
152+
153+
# initialize problem parameters
154+
problem_params = dict()
155+
problem_params['u0'] = 1.0 # initial value (for all instances)
156+
# use single values like this...
157+
# problem_params['lambdas'] = [[-1.0]]
158+
# .. or a list of values like this ...
159+
# problem_params['lambdas'] = [[-1.0, -2.0, 1j, -1j]]
160+
# .. or a whole block of values like this
161+
ilim_left = -11
162+
ilim_right = 0
163+
rlim_left = 0
164+
rlim_right = 11
165+
ilam = 1j * np.logspace(ilim_left, ilim_right, 11)
166+
rlam = -1 * np.logspace(rlim_left, rlim_right, 11)
167+
lambdas = []
168+
for rl in rlam:
169+
for il in ilam:
170+
lambdas.append(rl + il)
171+
problem_params['lambdas'] = [lambdas]
172+
# note: PFASST will do all of those at once, but without interaction (realized via diagonal matrix).
173+
# The propagation matrix will be diagonal too, corresponding to the respective lambda value.
174+
175+
# initialize step parameters
176+
step_params = dict()
177+
step_params['maxiter'] = 50
178+
179+
# initialize controller parameters
180+
controller_params = dict()
181+
controller_params['logger_level'] = 30
182+
controller_params['predict'] = False
183+
184+
# fill description dictionary for easy step instantiation
185+
description = dict()
186+
description['problem_class'] = testequation0d # pass problem class
187+
description['problem_params'] = problem_params # pass problem parameters
188+
description['dtype_u'] = cmesh # pass data type for u
189+
description['dtype_f'] = cmesh # pass data type for f
190+
description['sweeper_class'] = generic_implicit # pass sweeper
191+
description['sweeper_params'] = sweeper_params # pass sweeper parameters
192+
description['level_params'] = level_params # pass level parameters
193+
description['step_params'] = step_params # pass step parameters
194+
description['space_transfer_class'] = mesh_to_mesh_nocoarse # pass spatial transfer class
195+
description['space_transfer_params'] = dict() # pass paramters for spatial transfer
196+
197+
return description, controller_params
198+
199+
200+
def compare_controllers(type=None, par=0.0, f=None):
129201
"""
130202
A simple test program to compare PFASST runs with matrix-based and matrix-free controllers
131203
132204
Args:
133205
type (str): setup type
134-
mu (float) parameter for controlling stiffness
206+
par (float) parameter for controlling stiffness
135207
f: file handler
136208
"""
137209

@@ -140,13 +212,15 @@ def compare_controllers(type=None, mu=0.0, f=None):
140212
Tend = 1.0
141213

142214
if type == 'diffusion':
143-
description, controller_params = diffusion_setup(mu)
215+
description, controller_params = diffusion_setup(par)
144216
elif type == 'advection':
145-
description, controller_params = advection_setup(mu)
217+
description, controller_params = advection_setup(par)
218+
elif type == 'testequation':
219+
description, controller_params = testequation_setup()
146220
else:
147221
raise ValueError('No valis setup type provided, aborting..')
148222

149-
out = '\nWorking with %s setup and parameter %3.1e..' % (type, mu)
223+
out = '\nWorking with %s setup and parameter %3.1e..' % (type, par)
150224
f.write(out + '\n')
151225
print(out)
152226

@@ -178,7 +252,7 @@ def compare_controllers(type=None, mu=0.0, f=None):
178252
f.write(out + '\n')
179253
print(out)
180254

181-
assert diff < 2.0E-15, 'ERROR: difference between matrix-based and matrix-free result is too large, got %s' % diff
255+
assert diff < 2.3E-15, 'ERROR: difference between matrix-based and matrix-free result is too large, got %s' % diff
182256

183257
# filter statistics by type (number of iterations)
184258
filtered_stats_mat = filter_stats(stats_mat, type='niter')
@@ -201,12 +275,13 @@ def compare_controllers(type=None, mu=0.0, f=None):
201275

202276
def main():
203277

204-
mu_list = [1E-02, 1.0, 1E+02]
278+
par_list = [1E-02, 1.0, 1E+02]
205279

206-
f = open('comparison_matrix_vs_nomat_detail.txt', 'a')
207-
for mu in mu_list:
208-
compare_controllers(type='diffusion', mu=mu, f=f)
209-
compare_controllers(type='advection', mu=mu, f=f)
280+
f = open('comparison_matrix_vs_nomat_detail.txt', 'w')
281+
for par in par_list:
282+
compare_controllers(type='diffusion', par=par, f=f)
283+
compare_controllers(type='advection', par=par, f=f)
284+
compare_controllers(type='testequation', par=0.0, f=f)
210285
f.close()
211286

212287

pySDC/projects/matrixPFASST/compare_to_propagator.py

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def diffusion_setup(par=0.0):
3838
problem_params = dict()
3939
problem_params['nu'] = par # diffusion coefficient
4040
problem_params['freq'] = 4 # frequency for the test value
41-
problem_params['nvars'] = [127, 63] # number of degrees of freedom for each level
41+
problem_params['nvars'] = [127] # number of degrees of freedom for each level
4242

4343
# initialize step parameters
4444
step_params = dict()
@@ -140,34 +140,34 @@ def testequation_setup():
140140
level_params = dict()
141141
level_params['restol'] = 1E-08
142142
level_params['dt'] = 0.25
143-
level_params['nsweeps'] = [1, 1]
143+
level_params['nsweeps'] = [3, 1]
144144

145145
# initialize sweeper parameters
146146
sweeper_params = dict()
147147
sweeper_params['collocation_class'] = CollGaussRadau_Right
148-
sweeper_params['num_nodes'] = [3, 3]
148+
sweeper_params['num_nodes'] = [3, 2]
149149
sweeper_params['QI'] = 'LU'
150150
sweeper_params['spread'] = True
151151

152152
# initialize problem parameters
153153
problem_params = dict()
154154
problem_params['u0'] = 1.0 # initial value (for all instances)
155155
# use single values like this...
156-
problem_params['lambdas'] = [[-1.0]]
156+
# problem_params['lambdas'] = [[-1.0]]
157157
# .. or a list of values like this ...
158158
# problem_params['lambdas'] = [[-1.0, -2.0, 1j, -1j]]
159159
# .. or a whole block of values like this
160-
# ilim_left = -11
161-
# ilim_right = 0
162-
# rlim_left = 0
163-
# rlim_right = 11
164-
# ilam = 1j * np.logspace(ilim_left, ilim_right, 11)
165-
# rlam = -1 * np.logspace(rlim_left, rlim_right, 11)
166-
# lambdas = []
167-
# for rl in rlam:
168-
# for il in ilam:
169-
# lambdas.append(rl + il)
170-
# problem_params['lambdas'] = [lambdas]
160+
ilim_left = -11
161+
ilim_right = 0
162+
rlim_left = 0
163+
rlim_right = 11
164+
ilam = 1j * np.logspace(ilim_left, ilim_right, 11)
165+
rlam = -1 * np.logspace(rlim_left, rlim_right, 11)
166+
lambdas = []
167+
for rl in rlam:
168+
for il in ilam:
169+
lambdas.append(rl + il)
170+
problem_params['lambdas'] = [lambdas]
171171
# note: PFASST will do all of those at once, but without interaction (realized via diagonal matrix).
172172
# The propagation matrix will be diagonal too, corresponding to the respective lambda value.
173173

@@ -253,24 +253,27 @@ def compare_controllers(type=None, par=0.0, f=None):
253253
prop = controller.build_propagation_matrix(niter=niter)
254254

255255
err_prop_ex = np.linalg.norm(prop.dot(uinit.values) - uex.values)
256-
out = ' Difference between propagation and exact solution: %6.4e' % err_prop_ex
257-
f.write(out + '\n')
258-
print(out)
259256
err_mat_ex = np.linalg.norm(uend_mat.values - uex.values)
260-
out = ' Difference between matrix-PFASST and exact solution: %6.4e' % err_mat_ex
257+
out = ' Error (mat/prop) vs. exact solution: %6.4e -- %6.4e' % (err_mat_ex, err_prop_ex)
261258
f.write(out + '\n')
262259
print(out)
263260
err_mat_prop = np.linalg.norm(prop.dot(uinit.values) - uend_mat.values)
264261
out = ' Difference between matrix-PFASST and propagator: %6.4e' % err_mat_prop
265262
f.write(out + '\n')
266263
print(out)
267264

265+
assert err_mat_prop < 2.0E-14, \
266+
'ERROR: difference between matrix-based and propagator result is too large, got %s' % err_mat_prop
267+
268268

269269
def main():
270270

271+
par_list = [1E-02, 1.0, 1E+02]
272+
271273
f = open('comparison_matrix_vs_propagator_detail.txt', 'w')
272-
# compare_controllers(type='diffusion', par=1E-00, f=f)
273-
# compare_controllers(type='advection', par=1E-00, f=f)
274+
for par in par_list:
275+
compare_controllers(type='diffusion', par=par, f=f)
276+
compare_controllers(type='advection', par=par, f=f)
274277
compare_controllers(type='testequation', par=0.0, f=f)
275278
f.close()
276279

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from pySDC.projects.matrixPFASST.compare_to_matrixbased import main as A
2+
from pySDC.projects.matrixPFASST.compare_to_propagator import main as B
3+
4+
def test_matrixbased():
5+
A()
6+
7+
def test_propagator():
8+
B()
9+
10+

pySDC/tests/test_projects/test_matrixPFASST/test_mat_vs_nomat.py

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)