Skip to content

Commit 31eed1d

Browse files
author
Daniel Ruprecht
committed
Add special integrator which is defined by passing a stability function to the constructor. Allows to create tailored integrators for testing purposes
1 parent 0f09757 commit 31eed1d

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/special_integrator.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from integrator import integrator
2+
from solution import solution
3+
from solution_linear import solution_linear
4+
5+
class special_integrator(integrator):
6+
7+
def __init__(self, tstart, tend, nsteps, stab_function):
8+
super(special_integrator, self).__init__(tstart, tend, nsteps)
9+
self.stab_function = stab_function
10+
11+
def run(self, u0):
12+
assert isinstance(u0, solution_linear), "special_integrator can only be run for solutions of type solution_linear"
13+
for i in range(0,self.nsteps):
14+
u0.y = self.stab_function.dot(u0.y)
15+
16+
def get_update_matrix(self):
17+
return self.stab_function

tests/test_special_integrator.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import sys
2+
sys.path.append('../src')
3+
4+
import numpy as np
5+
from scipy import sparse
6+
from scipy import linalg
7+
from integrator import integrator
8+
from impeuler import impeuler
9+
from trapezoidal import trapezoidal
10+
from special_integrator import special_integrator
11+
from solution_linear import solution_linear
12+
from nose.tools import *
13+
import unittest
14+
import copy
15+
16+
class TestSpecialIntegrator(unittest.TestCase):
17+
18+
def setUp(self):
19+
self.ndof = np.random.randint(255)
20+
self.A = sparse.spdiags([ np.ones(self.ndof), -2.0*np.ones(self.ndof), np.ones(self.ndof)], [-1,0,1], self.ndof, self.ndof, format="csc")
21+
self.M = sparse.spdiags([ np.random.rand(self.ndof) ], [0], self.ndof, self.ndof, format="csc")
22+
self.sol = solution_linear(np.ones(self.ndof), self.A, self.M)
23+
24+
# Can instantiate object
25+
def test_caninstantiate(self):
26+
integ = special_integrator(0.0, 1.0, 10, sparse.eye(self.ndof))
27+
28+
# Throws if tend < tstart
29+
def test_tendbeforetstartthrows(self):
30+
with self.assertRaises(AssertionError):
31+
integ = special_integrator(1.0, 0.0, 10, sparse.eye(self.ndof))
32+
33+
# See if run function can be called
34+
def test_cancallrun(self):
35+
integ = special_integrator(0.0, 1.0, 10, sparse.eye(self.ndof))
36+
integ.run(self.sol)
37+
38+
# Make sure it provides identical solution to other integrator when stability function is given
39+
def test_reproducesimpeuler(self):
40+
ie = impeuler(0.0, 1.0, 25)
41+
M = sparse.csc_matrix(self.sol.M)
42+
A = sparse.csc_matrix(self.sol.A)
43+
Rmat = sparse.linalg.inv(M - ie.dt*A)
44+
Rmat = Rmat.dot(M)
45+
integ = special_integrator(0.0, 1.0, 25, Rmat)
46+
sol2 = copy.deepcopy(self.sol)
47+
ie.run(sol2)
48+
integ.run(self.sol)
49+
self.sol.axpy(-1.0, sol2)
50+
assert (self.sol.norm()<1e-14), "special_integrator did produce output identical to backward Euler"
51+
52+
def test_reproducetrapezoidal(self):
53+
trap = trapezoidal(0.0, 1.0, 25)
54+
M = sparse.csc_matrix(self.sol.M)
55+
A = sparse.csc_matrix(self.sol.A)
56+
Rmat = sparse.linalg.inv(M - 0.5*trap.dt*A)
57+
Rmat = Rmat.dot(M+0.5*trap.dt*A)
58+
integ = special_integrator(0.0, 1.0, 25, Rmat)
59+
sol2 = copy.deepcopy(self.sol)
60+
trap.run(sol2)
61+
integ.run(self.sol)
62+
self.sol.axpy(-1.0, sol2)
63+
assert (self.sol.norm()<1e-14), "special_integrator did produce output identical to trapezoidal rule"

0 commit comments

Comments
 (0)