Skip to content

Commit 9cad92c

Browse files
author
Daniel Ruprecht
committed
Allows to provide a matrix as argument for parareal and timemesh instead of the name of a coarse integrator. The matrix is used as stability matrix to initialise an object of type special_integrator
1 parent 43b8636 commit 9cad92c

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

scripts/plot_dispersion.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from parareal import parareal
55
from impeuler import impeuler
66
from intexact import intexact
7+
from special_integrator import special_integrator
78
from solution_linear import solution_linear
89
import numpy as np
910
#from scipy.sparse import linalg
@@ -62,10 +63,10 @@ def normalise(R, T, target):
6263
# symb_coarse = symb
6364
symb_coarse = -(1.0/dx)*(1.0 - np.exp(-1j*k_vec[i]*dx))
6465

66+
# Solution objects define the problem
6567
u0 = solution_linear(u0_val, np.array([[symb]],dtype='complex'))
6668
ucoarse = solution_linear(u0_val, np.array([[symb_coarse]],dtype='complex'))
67-
para = parareal(0.0, Tend, nslices, intexact, impeuler, nfine, ncoarse, 0.0, niter_v[0], u0)
68-
69+
6970
# get update matrix for imp Euler over one slice
7071
stab_fine = para.timemesh.slices[0].get_fine_update_matrix(u0)
7172
stab_fine = stab_fine
@@ -87,6 +88,10 @@ def normalise(R, T, target):
8788

8889
phase[2,i] = sol_coarse.real/k_vec[i]
8990
amp_factor[2,i] = np.exp(sol_coarse.imag)
91+
92+
# Create the parareal object to be used in the remainder
93+
para = parareal(0.0, Tend, nslices, intexact, impeuler, nfine, ncoarse, 0.0, niter_v[0], u0)
94+
9095

9196
# Compute Parareal phase velocity and amplification factor
9297
svds[0,i] = para.get_max_svd(ucoarse=ucoarse)

src/special_integrator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ def run(self, u0):
1313
for i in range(0,self.nsteps):
1414
u0.y = self.stab_function.dot(u0.y)
1515

16-
def get_update_matrix(self):
17-
return self.stab_function
16+
def get_update_matrix(self, sol):
17+
return self.stab_function**self.nsteps

src/timemesh.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from timeslice import timeslice
2+
from special_integrator import special_integrator
23
import numpy as np
34
from scipy.sparse import linalg
45
from scipy import sparse
@@ -21,7 +22,10 @@ def __init__(self, tstart, tend, nslices, fine, coarse, nsteps_fine, nsteps_coar
2122
# ... however, this has not yet been tested!!
2223
for i in range(0,nslices):
2324
ts_fine = fine(self.timemesh[i], self.timemesh[i+1], nsteps_fine)
24-
ts_coarse = coarse(self.timemesh[i], self.timemesh[i+1], nsteps_coarse)
25+
if sparse.issparse(coarse):
26+
ts_coarse = special_integrator(self.timemesh[i], self.timemesh[i+1], nsteps_coarse, coarse)
27+
else:
28+
ts_coarse = coarse(self.timemesh[i], self.timemesh[i+1], nsteps_coarse)
2529
self.slices.append( timeslice(ts_fine, ts_coarse, tolerance, iter_max) )
2630

2731
# Run the coarse method serially over all slices

tests/test_timemesh.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ def setUp(self):
2626
def test_caninstantiate(self):
2727
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 5)
2828

29+
# timemesh class can be instantiated with matrix as argument for coarse
30+
def test_caninstantiatewithmatrix(self):
31+
mat = sparse.eye(1)
32+
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, mat, self.nfine, self.ncoarse, 1e-10, 5)
33+
2934
# initial value can be set for first time slice
3035
def test_cansetinitial(self):
3136
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 5)
@@ -105,6 +110,20 @@ def test_runcoarse(self):
105110
err = abs(u[-1] - tm.get_coarse_value(self.nslices-1).y)
106111
assert err<1e-12, ("run_coarse and successive application of update matrix does not give identical results - error: %5.3e" % err)
107112

113+
# with coarse method provided as matrix, run_coarse is callable and provides expected output at very end
114+
def test_runcoarsewithmatrix(self):
115+
dt = (self.tend - self.tstart)/(float(self.nslices)*float(self.ncoarse))
116+
mat = sparse.csc_matrix(np.array([1.0/(1.0 - dt)]))
117+
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, mat, self.nfine, self.ncoarse, 1e-10, 5)
118+
tm.run_coarse(self.u0)
119+
u = np.array([1.0])
120+
Mat = tm.get_coarse_matrix(self.u0)
121+
b = np.zeros(self.nslices+1)
122+
b[0] = u[0]
123+
u = linalg.spsolve(Mat, b)
124+
err = abs(u[-1] - tm.get_coarse_value(self.nslices-1).y)
125+
assert err<1e-12, ("for coarse provided as matrix, run_coarse and successive application of update matrix does not give identical results - error: %5.3e" % err)
126+
108127
# run_fine is callable and provides expected output at very end
109128
def test_runfine(self):
110129
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 5)
@@ -130,6 +149,21 @@ def test_runcoarseintermediate(self):
130149
err = np.linalg.norm( tm.get_coarse_value(i).y - b, np.inf )
131150
assert err<2e-12, ("Successive application of update matrix does not reproduce intermediata coarse values generated by run_coarse. Error: %5.3e in slice %2i" % (err, i))
132151

152+
# with coarse provided as matrix, run_coarse provides expected intermediate values
153+
def test_runcoarseintermediatewithmatrix(self):
154+
dt = (self.tend - self.tstart)/(float(self.nslices)*float(self.ncoarse))
155+
mat = sparse.csc_matrix( np.array([1.0/(1.0 - dt)]) )
156+
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, mat, self.nfine, self.ncoarse, 1e-10, 5)
157+
tm.run_coarse(self.u0)
158+
u = np.array([1.0])
159+
Mat = tm.slices[0].int_coarse.get_update_matrix(self.u0)
160+
b = self.u0.y
161+
for i in range(0,3):
162+
# matrix update to end of slice
163+
b = Mat.dot(b)
164+
err = np.linalg.norm( tm.get_coarse_value(i).y - b, np.inf )
165+
assert err<2e-12, ("Successive application of update matrix does not reproduce intermediata coarse values generated by run_coarse. Error: %5.3e in slice %2i" % (err, i))
166+
133167
# run_fine provides expected intermediate values
134168
def test_runfineintermediate(self):
135169
tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 5)

0 commit comments

Comments
 (0)