Coverage for pySDC/implementations/transfer_classes/BaseTransfer_mass.py: 0%
84 statements
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
« prev ^ index » next coverage.py v7.6.9, created at 2024-12-20 14:51 +0000
1from pySDC.core.base_transfer import BaseTransfer
2from pySDC.core.errors import UnlockError
5class base_transfer_mass(BaseTransfer):
6 """
7 Standard base_transfer class
9 Attributes:
10 logger: custom logger for sweeper-related logging
11 params(__Pars): parameter object containing the custom parameters passed by the user
12 fine (pySDC.Level.level): reference to the fine level
13 coarse (pySDC.Level.level): reference to the coarse level
14 """
16 def restrict(self):
17 """
18 Space-time restriction routine
20 The routine applies the spatial restriction operator to teh fine values on the fine nodes, then reevaluates f
21 on the coarse level. This is used for the first part of the FAS correction tau via integration. The second part
22 is the integral over the fine values, restricted to the coarse level. Finally, possible tau corrections on the
23 fine level are restricted as well.
24 """
26 # get data for easier access
27 F = self.fine
28 G = self.coarse
30 PG = G.prob
31 PF = F.prob
33 SF = F.sweep
34 SG = G.sweep
36 # only if the level is unlocked at least by prediction
37 if not F.status.unlocked:
38 raise UnlockError('fine level is still locked, cannot use data from there')
40 # restrict fine values in space
41 tmp_u = []
42 for m in range(1, SF.coll.num_nodes + 1):
43 tmp_u.append(self.space_transfer.project(F.u[m]))
45 # restrict collocation values
46 G.u[0] = self.space_transfer.project(F.u[0])
47 for n in range(1, SG.coll.num_nodes + 1):
48 G.u[n] = self.Rcoll[n - 1, 0] * tmp_u[0]
49 for m in range(1, SF.coll.num_nodes):
50 G.u[n] += self.Rcoll[n - 1, m] * tmp_u[m]
52 # re-evaluate f on coarse level
53 G.f[0] = PG.eval_f(G.u[0], G.time)
54 for m in range(1, SG.coll.num_nodes + 1):
55 G.f[m] = PG.eval_f(G.u[m], G.time + G.dt * SG.coll.nodes[m - 1])
57 # build coarse level tau correction part
58 tauG = G.sweep.integrate()
60 for m in range(SG.coll.num_nodes):
61 tauG[m] = PG.apply_mass_matrix(G.u[m + 1]) - tauG[m]
63 # build fine level tau correction part
64 tauF = F.sweep.integrate()
66 for m in range(SF.coll.num_nodes):
67 tauF[m] = PF.apply_mass_matrix(F.u[m + 1]) - tauF[m]
69 # restrict fine level tau correction part in space
70 tmp_tau = []
71 for m in range(SF.coll.num_nodes):
72 tmp_tau.append(self.space_transfer.restrict(tauF[m]))
74 # restrict fine level tau correction part in collocation
75 tauFG = []
76 for n in range(1, SG.coll.num_nodes + 1):
77 tauFG.append(self.Rcoll[n - 1, 0] * tmp_tau[0])
78 for m in range(1, SF.coll.num_nodes):
79 tauFG[-1] += self.Rcoll[n - 1, m] * tmp_tau[m]
81 # build tau correction
82 for m in range(SG.coll.num_nodes):
83 G.tau[m] = tauG[m] - tauFG[m]
85 if F.tau[0] is not None:
86 # restrict possible tau correction from fine in space
87 tmp_tau = []
88 for m in range(SF.coll.num_nodes):
89 tmp_tau.append(self.space_transfer.restrict(F.tau[m]))
91 # restrict possible tau correction from fine in collocation
92 for n in range(SG.coll.num_nodes):
93 for m in range(SF.coll.num_nodes):
94 G.tau[n] += self.Rcoll[n, m] * tmp_tau[m]
95 else:
96 pass
98 # save u and rhs evaluations for interpolation
99 for m in range(1, SG.coll.num_nodes + 1):
100 G.uold[m] = PG.dtype_u(G.u[m])
101 G.fold[m] = PG.dtype_f(G.f[m])
103 # This is somewhat ugly, but we have to apply the mass matrix on u0 only on the finest level
104 if F.level_index == 0:
105 G.u[0] = self.space_transfer.restrict(PF.apply_mass_matrix(F.u[0]))
107 # works as a predictor
108 G.status.unlocked = True
110 return None
112 def prolong(self):
113 """
114 Space-time prolongation routine
116 This routine applies the spatial prolongation routine to the difference between the computed and the restricted
117 values on the coarse level and then adds this difference to the fine values as coarse correction.
118 """
120 # get data for easier access
121 F = self.fine
122 G = self.coarse
124 PF = F.prob
126 SF = F.sweep
127 SG = G.sweep
129 # only of the level is unlocked at least by prediction or restriction
130 if not G.status.unlocked:
131 raise UnlockError('coarse level is still locked, cannot use data from there')
133 # build coarse correction
135 # interpolate values in space first
136 tmp_u = []
137 for m in range(1, SG.coll.num_nodes + 1):
138 tmp_u.append(self.space_transfer.prolong(G.u[m] - G.uold[m]))
140 # interpolate values in collocation
141 # F.u[0] += tmp_u[0]
142 for n in range(1, SF.coll.num_nodes + 1):
143 for m in range(SG.coll.num_nodes):
144 F.u[n] += self.Pcoll[n - 1, m] * tmp_u[m]
146 # re-evaluate f on fine level
147 # F.f[0] = PF.eval_f(F.u[0], F.time)
148 for m in range(1, SF.coll.num_nodes + 1):
149 F.f[m] = PF.eval_f(F.u[m], F.time + F.dt * SF.coll.nodes[m - 1])
151 return None
153 def prolong_f(self):
154 """
155 Space-time prolongation routine w.r.t. the rhs f
157 This routine applies the spatial prolongation routine to the difference between the computed and the restricted
158 values on the coarse level and then adds this difference to the fine values as coarse correction.
159 """
161 # get data for easier access
162 F = self.fine
163 G = self.coarse
165 SF = F.sweep
166 SG = G.sweep
168 # only of the level is unlocked at least by prediction or restriction
169 if not G.status.unlocked:
170 raise UnlockError('coarse level is still locked, cannot use data from there')
172 # build coarse correction
174 # interpolate values in space first
175 tmp_u = []
176 tmp_f = []
177 for m in range(1, SG.coll.num_nodes + 1):
178 tmp_u.append(self.space_transfer.prolong(G.u[m] - G.uold[m]))
179 tmp_f.append(self.space_transfer.prolong(G.f[m] - G.fold[m]))
181 # interpolate values in collocation
182 for n in range(1, SF.coll.num_nodes + 1):
183 for m in range(SG.coll.num_nodes):
184 F.u[n] += self.Pcoll[n - 1, m] * tmp_u[m]
185 F.f[n] += self.Pcoll[n - 1, m] * tmp_f[m]
187 return None