44import re
55
66
7- SIMPLE_FORM = False
7+ SIMPLE_FORM = True
88
99class BlockIterationGenerator ():
1010
11- def __init__ (self ):
12- pass
13-
1411 def solve (self , lhs , rhs , u ):
1512 tmp = []
1613 for i in range (len (u )):
@@ -38,8 +35,8 @@ def createZeros(self, n):
3835 return sy .zeros (n , 1 )
3936
4037 def jacobi (self , A , u , f , w = 1 ):
41- D = A . lower_triangular ( 0 ). upper_triangular ( 0 )
42- return self .simplifyElementwise (u + w * D . inv () * (f - A * u ))
38+ Dinv = sy . diag ([ d ** ( - 1 ) for d in A . diagonal ()[:]], unpack = True )
39+ return self .simplifyElementwise (u + w * Dinv * (f - A * u ))
4340
4441 def gausseidel (self , A , u , f , A_c , u_res ):
4542 return self .solve (lhs = A_c * (u_res - u ), rhs = f - A * u , u = u_res )
@@ -59,13 +56,13 @@ def checkResults(self, u):
5956 tmp = gen .generateBlockRule ()
6057
6158 if SIMPLE_FORM :
62- dico = self .generateData ( 6 , 4 )
59+ dico = self .symbols
6360 subDico = {}
6461 prol = 1
6562 rest = 1
6663 for i , (phiOp , chiOp , TCtoF , TFtoC , prop ) in enumerate (zip (
6764 dico ['phi' ], dico ['chi' ], dico ['T_c_to_f' ], dico ['T_f_to_c' ],
68- ['F' , 'G' , 'H' , 'K' ])):
65+ ['F' , 'G' , 'H' , 'K' , 'L' , 'M' ])):
6966 sym = sy .symbols (prop , commutative = False )
7067 subDico [prol * phiOp ** (- 1 )* chiOp * rest ] = sym
7168 subDico [prol * (phiOp ** (- 1 )* chiOp )** 2 * rest ] = sym ** 2
@@ -81,31 +78,34 @@ def checkResults(self, u):
8178 else :
8279 gen .check (expr = u [i ], n = i + 1 )
8380
84- def generateData (self , n , L , pre_s = 1 , post_s = 0 ):
81+ def generateSymbols (self , nBlocks , nLevels , nPreSmooth = 1 , nPostSmooth = 0 ):
8582 save_symbols = {}
8683 u_0 = sy .Symbol (r'u_0' , commutative = False )
87- phi = [sy .Symbol (f'\phi_{ i } ' , commutative = False ) for i in range (L )]
88- chi = [sy .Symbol (f'\chi_{ i } ' , commutative = False ) for i in range (L )]
89- T_c_to_f = [sy .Symbol (f'T_{ i + 1 } ^{ i } ' , commutative = False ) for i in range (L )]
90- T_f_to_c = [sy .Symbol (f'T_{ i } ^{ i + 1 } ' , commutative = False ) for i in range (L )]
91- A = [sy .Matrix (np .eye (n , dtype = int ) * phi [i ]) + sy .Matrix (np .eye (n , k = - 1 , dtype = int ) * - chi [i ]) for i in
92- range (L )]
84+ phi = [sy .Symbol (f'\phi_{ i } ' , commutative = False ) for i in range (nLevels )]
85+ chi = [sy .Symbol (f'\chi_{ i } ' , commutative = False ) for i in range (nLevels )]
86+ T_c_to_f = [sy .Symbol (f'T_{ i + 1 } ^{ i } ' , commutative = False ) for i in range (nLevels )]
87+ T_f_to_c = [sy .Symbol (f'T_{ i } ^{ i + 1 } ' , commutative = False ) for i in range (nLevels )]
88+ A = [sy .Matrix (np .eye (nBlocks , dtype = int ) * phi [i ]) + sy .Matrix (np .eye (nBlocks , k = - 1 , dtype = int ) * - chi [i ]) for i in
89+ range (nLevels )]
9390 u_k = [
94- [self .createVec ('u^0' , n = n , ss = save_symbols ), self .createVec ('u^0' , n = n , ss = save_symbols )] if i == 0 else [
95- self .createVec (f'u^0_{ i } ' , n = n , ss = save_symbols ),
96- self .createZeros (n )] for i in range (L )]
91+ [self .createVec ('u^0' , n = nBlocks , ss = save_symbols ),
92+ self .createVec ('u^0' , n = nBlocks , ss = save_symbols )] if i == 0 else [
93+ self .createVec (f'u^0_{ i } ' , n = nBlocks , ss = save_symbols ),
94+ self .createZeros (nBlocks )] for i in range (nLevels )]
9795 u_k_1 = [
98- [self .createVec ('u^1' , n = n , ss = save_symbols ), self .createVec ('u^1' , n = n , ss = save_symbols )] if i == 0 else [
99- self .createVec (f'u^1_{ i } ' , n = n , ss = save_symbols ),
100- self .createVec (f'u^1_{ i } ' , n = n , ss = save_symbols )] for i in
101- range (L )]
102- f = [sy .Matrix ([[chi [0 ] * u_0 if i == 0 else 0 for i in range (n )]]).transpose () if i == 0 else None for i in
103- range (L )]
104- pre_smoothing = [pre_s for _ in range (L )]
105- post_smoothing = [post_s for _ in range (L )]
106- return {
107- 'L' : L ,
108- 'n' : n ,
96+ [self .createVec ('u^1' , n = nBlocks , ss = save_symbols ),
97+ self .createVec ('u^1' , n = nBlocks , ss = save_symbols )] if i == 0 else [
98+ self .createVec (f'u^1_{ i } ' , n = nBlocks , ss = save_symbols ),
99+ self .createVec (f'u^1_{ i } ' , n = nBlocks , ss = save_symbols )] for i in
100+ range (nLevels )]
101+ f = [sy .Matrix ([[chi [0 ] * u_0 if i == 0 else 0 for i in range (nBlocks )]]).transpose ()
102+ if i == 0 else None for i in range (nLevels )]
103+ pre_smoothing = [nPreSmooth for _ in range (nLevels )]
104+ post_smoothing = [nPostSmooth for _ in range (nLevels )]
105+
106+ self .symbols = {
107+ 'L' : nLevels ,
108+ 'n' : nBlocks ,
109109 'phi' : phi ,
110110 'chi' : chi ,
111111 'T_c_to_f' : T_c_to_f ,
@@ -117,21 +117,23 @@ def generateData(self, n, L, pre_s=1, post_s=0):
117117 'pre_smoothing' : pre_smoothing ,
118118 'post_smoothing' : post_smoothing ,
119119 }
120+ return self .symbols
120121
121122
122123class PararealGenerator (BlockIterationGenerator ):
123124
124- def __init__ (self , n ):
125- super ().__init__ ()
126- res = self .parareal (settings = self .generateData (n = n , L = 2 ))
127- self .checkResults (res )
128-
129- def parareal (self , settings , overlapping = False ):
130- u = settings ['u_k' ]
131- chi = settings ['chi' ]
132- A = settings ['A' ]
133- f = settings ['f' ]
134- u_k_1 = settings ['u_k_1' ]
125+ def __init__ (self , nBlocks ):
126+ self .generateSymbols (nBlocks = nBlocks , nLevels = 2 )
127+ self .res = self .parareal ()
128+ self .checkResults (self .res )
129+
130+ def parareal (self , overlapping = False ):
131+ symbols = self .symbols
132+ u = symbols ['u_k' ]
133+ chi = symbols ['chi' ]
134+ A = symbols ['A' ]
135+ f = symbols ['f' ]
136+ u_k_1 = symbols ['u_k_1' ]
135137 jac = self .jacobi (u = u [0 ][1 ], A = A [0 ], f = f [0 ])
136138 if overlapping :
137139 jac = self .jacobi (u = jac , A = A [0 ], f = f [0 ])
@@ -140,23 +142,25 @@ def parareal(self, settings, overlapping=False):
140142
141143
142144class MultilevelGenerator (BlockIterationGenerator ):
143- def __init__ (self , n , L , pre_smoothing = 1 , post_smoothing = 1 ):
144- super ().__init__ ()
145- res = self .multilevel (
146- setting = self .generateData (n = n , L = L , pre_s = pre_smoothing , post_s = post_smoothing ))
147- self .checkResults (res )
148-
149- def multilevel (self , setting , l = 0 ):
150- L = setting ['L' ] - 1
151- T_c_f_s = setting ['T_c_to_f' ]
152- T_f_c_s = setting ['T_f_to_c' ]
153- A = setting ['A' ]
154- u_k = setting ['u_k' ]
155- u_k_1 = setting ['u_k_1' ]
156- f = setting ['f' ]
157- pre = setting ['pre_smoothing' ]
158- post = setting ['post_smoothing' ]
159- chi = setting ['chi' ]
145+
146+ def __init__ (self , nBlocks , nLevels , nPreSmooth = 1 , nPostSmooth = 1 ):
147+ self .generateSymbols (nBlocks = nBlocks , nLevels = nLevels , nPreSmooth = nPreSmooth , nPostSmooth = nPostSmooth )
148+ self .res = self .multilevel ()
149+ self .checkResults (self .res )
150+
151+ def multilevel (self , l = 0 ):
152+ symbols = self .symbols
153+
154+ L = symbols ['L' ] - 1
155+ T_c_f_s = symbols ['T_c_to_f' ]
156+ T_f_c_s = symbols ['T_f_to_c' ]
157+ A = symbols ['A' ]
158+ u_k = symbols ['u_k' ]
159+ u_k_1 = symbols ['u_k_1' ]
160+ f = symbols ['f' ]
161+ pre = symbols ['pre_smoothing' ]
162+ post = symbols ['post_smoothing' ]
163+ chi = symbols ['chi' ]
160164
161165 state = {}
162166 state2 = {}
@@ -179,7 +183,7 @@ def multilevel(self, setting, l=0):
179183 else :
180184 u_k_1 [l ][1 ] = self .jacobi (u = u_k_1 [l ][1 ], A = A [l ], f = f [l ])
181185 f [l + 1 ] = (T_f_c_s [l ] * (f [l ] - A [l ] * u_k_1 [l ][1 ]))
182- self .multilevel (l = l + 1 , setting = setting )
186+ self .multilevel (l = l + 1 )
183187 tmp = self .solve (lhs = u_k_1 [l ][0 ],
184188 rhs = u_k_1 [l ][1 ] + T_c_f_s [l ] * u_k_1 [l + 1 ][0 ],
185189 u = u_k_1 [l + 1 ][0 ]).subs (state2 )
@@ -285,5 +289,6 @@ def u(n, k):
285289 return tmp
286290
287291
288- # PararealGenerator(n=6)
289- MultilevelGenerator (n = 6 , L = 3 , pre_smoothing = 1 , post_smoothing = 0 )
292+ if __name__ == "__main__" :
293+ # PararealGenerator(n=4)
294+ MultilevelGenerator (nBlocks = 7 , nLevels = 3 , nPreSmooth = 1 , nPostSmooth = 0 )
0 commit comments