# Coverage for pySDC/implementations/problem_classes/FastWaveSlowWave_0D.py: 100%

## 40 statements

, created at 2024-09-20 17:10 +0000

1import numpy as np

3from pySDC.core.errors import ParameterError

4from pySDC.core.problem import Problem

5from pySDC.implementations.datatype_classes.mesh import mesh, imex_mesh

8# noinspection PyUnusedLocal

9class swfw_scalar(Problem):

10 r"""

11 This class implements the fast-wave-slow-wave scalar problem fully investigated in [1]_. It is defined by

13 .. math::

14 \frac{d u(t)}{dt} = \lambda_f u(t) + \lambda_s u(t),

16 where :math:\lambda_f denotes the part of the fast wave, and :math:\lambda_s is the part of the slow wave with

17 :math:\lambda_f \gg \lambda_s. Let :math:u_0 be the initial condition to the problem, then the exact solution

18 is given by

20 .. math::

21 u(t) = u_0 \exp((\lambda_f + \lambda_s) t).

23 Parameters

24 ----------

25 lambda_s : np.1darray, optional

26 Part of the slow wave :math:\lambda_s.

27 lambda_f : np.1darray, optional

28 Part of the fast wave :math:\lambda_f.

29 u0 : np.1darray, optional

30 Initial condition of the problem.

32 References

33 ----------

34 .. [1] D. Ruprecht, R. Speck. Spectral deferred corrections with fast-wave slow-wave splitting.

35 SIAM J. Sci. Comput. Vol. 38 No. 4 (2016).

36 """

38 dtype_u = mesh

39 dtype_f = imex_mesh

41 def __init__(self, lambda_s=-1, lambda_f=-1000, u0=1):

42 """Initialization routine"""

44 init = ([lambda_s.size, lambda_f.size], None, np.dtype('complex128'))

45 super().__init__(init)

46 self._makeAttributeAndRegister('lambda_s', 'lambda_f', 'u0', localVars=locals(), readOnly=True)

48 def solve_system(self, rhs, factor, u0, t):

49 r"""

50 Simple im=nversion of :math:(1 - \Delta t \cdot \lambda)\vec{u} = \vec{rhs}.

52 Parameters

53 ----------

54 rhs : dtype_f

55 Right-hand side for the nonlinear system.

56 factor : float

57 Abbrev. for the node-to-node stepsize (or any other factor required).

58 u0 : dtype_u

59 Initial guess for the iterative solver (not used here so far).

60 t : float

61 Current time (e.g. for time-dependent BCs).

63 Returns

64 -------

65 me : dtype_u

66 The solution as mesh.

67 """

69 me = self.dtype_u(self.init)

70 for i in range(self.lambda_s.size):

71 for j in range(self.lambda_f.size):

72 me[i, j] = rhs[i, j] / (1.0 - factor * self.lambda_f[j])

74 return me

76 def __eval_fexpl(self, u, t):

77 """

78 Helper routine to evaluate the explicit part of the right-hand side.

80 Parameters

81 ----------

82 u : dtype_u

83 Current values of the numerical solution.

84 t : float

85 Current time at which the numerical solution is computed (not used here).

87 Returns

88 -------

89 fexpl : dtype_u

90 Explicit part of right-hand side.

91 """

93 fexpl = self.dtype_u(self.init)

94 for i in range(self.lambda_s.size):

95 for j in range(self.lambda_f.size):

96 fexpl[i, j] = self.lambda_s[i] * u[i, j]

97 return fexpl

99 def __eval_fimpl(self, u, t):

100 """

101 Helper routine to evaluate the implicit part of the right-hand side.

103 Parameters

104 ----------

105 u : dtype_u

106 Current values of the numerical solution.

107 t : float

108 Current time at which the numerical solution is computed (not used here).

110 Returns

111 -------

112 fimpl : dtype_u

113 Implicit part of right-hand side.

114 """

116 fimpl = self.dtype_u(self.init)

117 for i in range(self.lambda_s.size):

118 for j in range(self.lambda_f.size):

119 fimpl[i, j] = self.lambda_f[j] * u[i, j]

121 return fimpl

123 def eval_f(self, u, t):

124 """

125 Routine to evaluate both parts of the right-hand side of the problem.

127 Parameters

128 ----------

129 u : dtype_u

130 Current values of the numerical solution.

131 t : float

132 Current time at which the numerical solution is computed.

134 Returns

135 -------

136 f : dtype_f

137 The right-hand side divided into two parts.

138 """

140 f = self.dtype_f(self.init)

141 f.impl = self.__eval_fimpl(u, t)

142 f.expl = self.__eval_fexpl(u, t)

143 return f

145 def u_exact(self, t):

146 r"""

147 Routine to compute the exact solution at time :math:t.

149 Parameters

150 ----------

151 t : float

152 Time of the exact solution.

154 Returns

155 -------

156 me : dtype_u

157 The exact solution.

158 """

160 me = self.dtype_u(self.init)

161 for i in range(self.lambda_s.size):

162 for j in range(self.lambda_f.size):

163 me[i, j] = self.u0 * np.exp((self.lambda_f[j] + self.lambda_s[i]) * t)

164 return me