Skip to content

Commit d0dda36

Browse files
committed
added test equation
1 parent eac81fd commit d0dda36

File tree

3 files changed

+190
-9
lines changed

3 files changed

+190
-9
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from __future__ import division
2+
import numpy as np
3+
import scipy.sparse as sp
4+
from scipy.sparse.linalg import splu
5+
6+
from pySDC.core.Problem import ptype
7+
from pySDC.core.Errors import ParameterError, ProblemError
8+
9+
10+
# noinspection PyUnusedLocal
11+
class testequation0d(ptype):
12+
"""
13+
Example implementing a bundle of test equations at once (via diagonal matrix)
14+
15+
Attributes:
16+
A: digonal matrix containing the parameters
17+
"""
18+
19+
def __init__(self, problem_params, dtype_u, dtype_f):
20+
"""
21+
Initialization routine
22+
23+
Args:
24+
problem_params (dict): custom parameters for the example
25+
dtype_u: mesh data type for solution
26+
dtype_f: mesh data type for RHS
27+
"""
28+
29+
# these parameters will be used later, so assert their existence
30+
essential_keys = ['lambdas', 'u0']
31+
for key in essential_keys:
32+
if key not in problem_params:
33+
msg = 'need %s to instantiate problem, only got %s' % (key, str(problem_params.keys()))
34+
raise ParameterError(msg)
35+
36+
assert not any(isinstance(i, list) for i in problem_params['lambdas']), \
37+
'ERROR: expect flat list here, got %s' % problem_params['lambdas']
38+
nvars = len(problem_params['lambdas'])
39+
assert nvars > 0, 'ERROR: expect at least one lambda parameter here'
40+
41+
# invoke super init, passing number of dofs, dtype_u and dtype_f
42+
super(testequation0d, self).__init__(init=nvars, dtype_u=dtype_u, dtype_f=dtype_f,
43+
params=problem_params)
44+
45+
self.A = self.__get_A(self.params.lambdas)
46+
47+
@staticmethod
48+
def __get_A(lambdas):
49+
"""
50+
Helper function to assemble FD matrix A in sparse format
51+
52+
Args:
53+
lambdas (list): list of lambda parameters
54+
55+
Returns:
56+
scipy.sparse.csc_matrix: diagonal matrix A in CSC format
57+
"""
58+
59+
A = sp.diags(lambdas)
60+
return A
61+
62+
def eval_f(self, u, t):
63+
"""
64+
Routine to evaluate the RHS
65+
66+
Args:
67+
u (dtype_u): current values
68+
t (float): current time
69+
70+
Returns:
71+
dtype_f: the RHS
72+
"""
73+
74+
f = self.dtype_f(self.init)
75+
f.values = self.A.dot(u.values)
76+
return f
77+
78+
def solve_system(self, rhs, factor, u0, t):
79+
"""
80+
Simple linear solver for (I-factor*A)u = rhs
81+
82+
Args:
83+
rhs (dtype_f): right-hand side for the linear system
84+
factor (float): abbrev. for the local stepsize (or any other factor required)
85+
u0 (dtype_u): initial guess for the iterative solver
86+
t (float): current time (e.g. for time-dependent BCs)
87+
88+
Returns:
89+
dtype_u: solution as mesh
90+
"""
91+
92+
me = self.dtype_u(self.init)
93+
L = splu(sp.eye(self.params.nvars, format='csc') - factor * self.A)
94+
me.values = L.solve(rhs.values)
95+
return me
96+
97+
def u_exact(self, t):
98+
"""
99+
Routine to compute the exact solution at time t
100+
101+
Args:
102+
t (float): current time
103+
104+
Returns:
105+
dtype_u: exact solution
106+
"""
107+
108+
me = self.dtype_u(self.init)
109+
me.values = self.params.u0 * np.exp(t * np.array(self.params.lambdas))
110+
return me

pySDC/projects/matrixPFASST/allinclusive_matrix_nonMPI.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pySDC.implementations.controller_classes.allinclusive_multigrid_nonMPI import allinclusive_multigrid_nonMPI
66

77
from pySDC.implementations.datatype_classes.mesh import mesh
8+
from pySDC.implementations.datatype_classes.complex_mesh import mesh as cmesh
89
from pySDC.implementations.collocation_classes.gauss_radau_right import CollGaussRadau_Right
910
from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
1011

@@ -26,9 +27,9 @@ def __init__(self, num_procs, controller_params, description):
2627
description: all the parameters to set up the rest (levels, problems, transfer, ...)
2728
"""
2829

29-
assert description['dtype_u'] is mesh, \
30+
assert description['dtype_u'] is mesh or cmesh, \
3031
'ERROR: matrix version will only work with mesh data type for u, got %s' % description['dtype_u']
31-
assert description['dtype_f'] is mesh, \
32+
assert description['dtype_f'] is mesh or cmesh, \
3233
'ERROR: matrix version will only work with mesh data type for f, got %s' % description['dtype_f']
3334
assert description['sweeper_class'] is generic_implicit, \
3435
'ERROR: matrix version will only work with generic_implicit sweeper, got %s' % description['sweeper_class']

pySDC/projects/matrixPFASST/compare_to_propagator.py

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
from pySDC.implementations.problem_classes.HeatEquation_1D_FD import heat1d
44
from pySDC.implementations.problem_classes.AdvectionEquation_1D_FD import advection1d
5+
from pySDC.implementations.problem_classes.TestEquation_0D import testequation0d
56
from pySDC.implementations.datatype_classes.mesh import mesh
7+
from pySDC.implementations.datatype_classes.complex_mesh import mesh as cmesh
68
from pySDC.implementations.collocation_classes.gauss_radau_right import CollGaussRadau_Right
79
from pySDC.implementations.sweeper_classes.generic_implicit import generic_implicit
810
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
912
from pySDC.projects.matrixPFASST.allinclusive_matrix_nonMPI import allinclusive_matrix_nonMPI
1013

1114
from pySDC.helpers.stats_helper import filter_stats, sort_stats
@@ -28,7 +31,7 @@ def diffusion_setup(par=0.0):
2831
sweeper_params = dict()
2932
sweeper_params['collocation_class'] = CollGaussRadau_Right
3033
sweeper_params['num_nodes'] = 3
31-
sweeper_params['QI'] = 'LU' # For the IMEX sweeper, the LU-trick can be activated for the implicit part
34+
sweeper_params['QI'] = 'LU'
3235
sweeper_params['spread'] = True
3336

3437
# initialize problem parameters
@@ -84,7 +87,7 @@ def advection_setup(par=0.0):
8487
sweeper_params = dict()
8588
sweeper_params['collocation_class'] = CollGaussRadau_Right
8689
sweeper_params['num_nodes'] = [3]
87-
sweeper_params['QI'] = ['LU'] # For the IMEX sweeper, the LU-trick can be activated for the implicit part
90+
sweeper_params['QI'] = ['LU']
8891
sweeper_params['spread'] = True
8992

9093
# initialize problem parameters
@@ -126,6 +129,73 @@ def advection_setup(par=0.0):
126129
return description, controller_params
127130

128131

132+
def testequation_setup():
133+
"""
134+
Setup routine for the test equation
135+
136+
Args:
137+
par (float): parameter for controlling stiffness
138+
"""
139+
# initialize level parameters
140+
level_params = dict()
141+
level_params['restol'] = 1E-08
142+
level_params['dt'] = 0.25
143+
level_params['nsweeps'] = [3]
144+
145+
# initialize sweeper parameters
146+
sweeper_params = dict()
147+
sweeper_params['collocation_class'] = CollGaussRadau_Right
148+
sweeper_params['num_nodes'] = [3]
149+
sweeper_params['QI'] = 'LU'
150+
sweeper_params['spread'] = True
151+
152+
# initialize problem parameters
153+
problem_params = dict()
154+
problem_params['u0'] = 1.0 # initial value (for all instances)
155+
# use single values like this...
156+
problem_params['lambdas'] = [[-1.0]]
157+
# .. or a list of values like this ...
158+
problem_params['lambdas'] = [[-1.0, -2.0, 1j, -1j]]
159+
# .. 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]
171+
# note: PFASST will do all of those at once, but without interaction (realized via diagonal matrix).
172+
# The propagation matrix will be diagonal too, corresponding to the respective lambda value.
173+
174+
# initialize step parameters
175+
step_params = dict()
176+
step_params['maxiter'] = 50
177+
178+
# initialize controller parameters
179+
controller_params = dict()
180+
controller_params['logger_level'] = 30
181+
controller_params['predict'] = False
182+
183+
# fill description dictionary for easy step instantiation
184+
description = dict()
185+
description['problem_class'] = testequation0d # pass problem class
186+
description['problem_params'] = problem_params # pass problem parameters
187+
description['dtype_u'] = cmesh # pass data type for u
188+
description['dtype_f'] = cmesh # pass data type for f
189+
description['sweeper_class'] = generic_implicit # pass sweeper
190+
description['sweeper_params'] = sweeper_params # pass sweeper parameters
191+
description['level_params'] = level_params # pass level parameters
192+
description['step_params'] = step_params # pass step parameters
193+
description['space_transfer_class'] = mesh_to_mesh_nocoarse # pass spatial transfer class
194+
description['space_transfer_params'] = dict() # pass paramters for spatial transfer
195+
196+
return description, controller_params
197+
198+
129199
def compare_controllers(type=None, par=0.0, f=None):
130200
"""
131201
A simple test program to compare PFASST runs with matrix-based and matrix-free controllers
@@ -144,6 +214,8 @@ def compare_controllers(type=None, par=0.0, f=None):
144214
description, controller_params = diffusion_setup(par)
145215
elif type == 'advection':
146216
description, controller_params = advection_setup(par)
217+
elif type == 'testequation':
218+
description, controller_params = testequation_setup()
147219
else:
148220
raise ValueError('No valis setup type provided, aborting..')
149221

@@ -196,12 +268,10 @@ def compare_controllers(type=None, par=0.0, f=None):
196268

197269
def main():
198270

199-
par_list = [1E-02, 1.0, 1E+02]
200-
201271
f = open('comparison_matrix_vs_propagator_detail.txt', 'a')
202-
for par in par_list:
203-
compare_controllers(type='diffusion', par=par, f=f)
204-
compare_controllers(type='advection', par=par, f=f)
272+
# compare_controllers(type='diffusion', par=1E-00, f=f)
273+
# compare_controllers(type='advection', par=1E-00, f=f)
274+
compare_controllers(type='testequation', par=0.0, f=f)
205275
f.close()
206276

207277

0 commit comments

Comments
 (0)