Coverage for pySDC / projects / RayleighBenard / sweepers.py: 64%

39 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-27 07:06 +0000

1from pySDC.implementations.sweeper_classes.imex_1st_order import imex_1st_order 

2from pySDC.implementations.sweeper_classes.imex_1st_order_MPI import imex_1st_order_MPI 

3 

4 

5class imex_1st_order_diagonal_serial(imex_1st_order): 

6 def update_nodes(self): 

7 """ 

8 Update the u- and f-values at the collocation nodes -> corresponds to a single sweep over all nodes 

9 

10 Returns: 

11 None 

12 """ 

13 # get current level and problem description 

14 L = self.level 

15 P = L.prob 

16 

17 # only if the level has been touched before 

18 assert L.status.unlocked 

19 

20 # get number of collocation nodes for easier access 

21 M = self.coll.num_nodes 

22 

23 # gather all terms which are known already (e.g. from the previous iteration) 

24 # this corresponds to u0 + QF(u^k) - QIFI(u^k) - QEFE(u^k) + tau 

25 

26 # get QF(u^k) 

27 integral = self.integrate() 

28 for m in range(M): 

29 # subtract QIFI(u^k)_m + QEFE(u^k)_m 

30 for j in range(1, M + 1): 

31 integral[m] -= L.dt * (self.QI[m + 1, j] * L.f[j].impl + self.QE[m + 1, j] * L.f[j].expl) 

32 # add initial value 

33 integral[m] += L.u[0] 

34 # add tau if associated 

35 if L.tau[m] is not None: 

36 integral[m] += L.tau[m] 

37 

38 # do the sweep 

39 for m in range(0, M) if L.status.sweep < L.params.nsweeps else [M - 1]: 

40 # build rhs, consisting of the known values from above and new values from previous nodes (at k+1) 

41 rhs = P.dtype_u(integral[m]) 

42 for j in range(1, m + 1): 

43 rhs += L.dt * (self.QI[m + 1, j] * L.f[j].impl + self.QE[m + 1, j] * L.f[j].expl) 

44 

45 # implicit solve with prefactor stemming from QI 

46 L.u[m + 1] = P.solve_system( 

47 rhs, L.dt * self.QI[m + 1, m + 1], L.u[m + 1], L.time + L.dt * self.coll.nodes[m] 

48 ) 

49 

50 # update function values 

51 if L.status.sweep < L.params.nsweeps: 

52 L.f[m + 1] = P.eval_f(L.u[m + 1], L.time + L.dt * self.coll.nodes[m]) 

53 

54 # indicate presence of new values at this level 

55 L.status.updated = True 

56 

57 return None 

58 

59 

60class imex_1st_order_MPI_fixed_k(imex_1st_order_MPI): 

61 def update_nodes(self): 

62 """ 

63 Update the u- and f-values at the collocation nodes -> corresponds to a single sweep over all nodes 

64 

65 Returns: 

66 None 

67 """ 

68 

69 L = self.level 

70 P = L.prob 

71 

72 # only if the level has been touched before 

73 assert L.status.unlocked 

74 

75 # get number of collocation nodes for easier access 

76 

77 # gather all terms which are known already (e.g. from the previous iteration) 

78 # this corresponds to u0 + QF(u^k) - QdF(u^k) + tau 

79 

80 # get QF(u^k) 

81 rhs = self.integrate() 

82 

83 # subtract QdF(u^k) 

84 rhs -= L.dt * (self.QI[self.rank + 1, self.rank + 1] * L.f[self.rank + 1].impl) 

85 

86 # add initial conditions 

87 rhs += L.u[0] 

88 # add tau if associated 

89 if L.tau[self.rank] is not None: 

90 rhs += L.tau[self.rank] 

91 

92 # implicit solve with prefactor stemming from the diagonal of Qd 

93 L.u[self.rank + 1] = P.solve_system( 

94 rhs, 

95 L.dt * self.QI[self.rank + 1, self.rank + 1], 

96 L.u[self.rank + 1], 

97 L.time + L.dt * self.coll.nodes[self.rank], 

98 ) 

99 # update function values 

100 if L.status.sweep < L.params.nsweeps: 

101 L.f[self.rank + 1] = P.eval_f(L.u[self.rank + 1], L.time + L.dt * self.coll.nodes[self.rank]) 

102 

103 # indicate presence of new values at this level 

104 L.status.updated = True 

105 

106 return None