Coverage for pySDC/implementations/problem_classes/FastWaveSlowWave_0D.py: 100%
40 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
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