Coverage for pySDC/implementations/problem_classes/AdvectionEquation_ND_FD.py: 65%
23 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-25 20:28 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-25 20:28 +0000
1from pySDC.implementations.problem_classes.generic_ND_FD import GenericNDimFinDiff
4# noinspection PyUnusedLocal
5class advectionNd(GenericNDimFinDiff):
6 r"""
7 Example implementing the unforced ND advection equation with periodic
8 or Dirichlet boundary conditions in :math:`[0,1]^N`
10 .. math::
11 \frac{\partial u}{\partial t} = -c \frac{\partial u}{\partial x},
13 and initial solution of the form
15 .. math::
16 u({\bf x},0) = \prod_{i=1}^N \sin(f\pi x_i),
18 with :math:`x_i` the coordinate in :math:`i^{th}` dimension.
19 Discretization uses central finite differences.
21 Parameters
22 ----------
23 nvars : int of tuple, optional
24 Spatial resolution (same in all dimensions). Using a tuple allows to
25 consider several dimensions, e.g ``nvars=(16,16)`` for a 2D problem.
26 c : float, optional
27 Advection speed (same in all dimensions).
28 freq : int of tuple, optional
29 Spatial frequency :math:`f` of the initial conditions, can be tuple.
30 stencil_type : str, optional
31 Type of the finite difference stencil.
32 order : int, optional
33 Order of the finite difference discretization.
34 lintol : float, optional
35 Tolerance for spatial solver (GMRES).
36 liniter : int, optional
37 Max. iterations number for GMRES.
38 solver_type : str, optional
39 Solve the linear system directly or using GMRES or CG
40 bc : str, optional
41 Boundary conditions, either ``'periodic'`` or ``'dirichlet'``.
42 sigma : float, optional
43 If ``freq=-1`` and ``ndim=1``, uses a Gaussian initial solution of the form
45 .. math::
46 u(x,0) = e^{
47 \frac{\displaystyle 1}{\displaystyle 2}
48 \left(
49 \frac{\displaystyle x-1/2}{\displaystyle \sigma}
50 \right)^2
51 }
53 Attributes
54 ----------
55 A : sparse matrix (CSC)
56 FD discretization matrix of the ND grad operator.
57 Id : sparse matrix (CSC)
58 Identity matrix of the same dimension as A.
60 Note
61 ----
62 Args can be set as values or as tuples, which will increase the dimension.
63 Do, however, take care that all spatial parameters have the same dimension.
64 """
66 def __init__(
67 self,
68 nvars=512,
69 c=1.0,
70 freq=2,
71 stencil_type='center',
72 order=2,
73 lintol=1e-12,
74 liniter=10000,
75 solver_type='direct',
76 bc='periodic',
77 sigma=6e-2,
78 ):
79 super().__init__(nvars, -c, 1, freq, stencil_type, order, lintol, liniter, solver_type, bc)
81 if solver_type == 'CG': # pragma: no cover
82 self.logger.warning('CG is not usually used for advection equation')
83 self._makeAttributeAndRegister('c', localVars=locals(), readOnly=True)
84 self._makeAttributeAndRegister('sigma', localVars=locals())
86 def u_exact(self, t, **kwargs):
87 r"""
88 Routine to compute the exact solution at time :math:`t`.
90 Parameters
91 ----------
92 t : float
93 Time of the exact solution.
94 **kwargs : dict
95 Additional arguments (that won't be used).
97 Returns
98 -------
99 sol : dtype_u
100 The exact solution.
101 """
102 if 'u_init' in kwargs.keys() or 't_init' in kwargs.keys():
103 self.logger.warning(
104 f'{type(self).__name__} uses an analytic exact solution from t=0. If you try to compute the local error, you will get the global error instead!'
105 )
107 # Initialize pointers and variables
108 ndim, freq, c, sigma, sol = self.ndim, self.freq, self.c, self.sigma, self.u_init
110 if ndim == 1:
111 x = self.grids
112 if freq[0] >= 0:
113 sol[:] = self.xp.sin(self.xp.pi * freq[0] * (x - c * t))
114 elif freq[0] == -1:
115 # Gaussian initial solution
116 sol[:] = self.xp.exp(-0.5 * (((x - (c * t)) % 1.0 - 0.5) / sigma) ** 2)
118 elif ndim == 2:
119 x, y = self.grids
120 sol[:] = self.xp.sin(self.xp.pi * freq[0] * (x - c * t)) * self.xp.sin(self.xp.pi * freq[1] * (y - c * t))
122 elif ndim == 3:
123 x, y, z = self.grids
124 sol[:] = (
125 self.xp.sin(self.xp.pi * freq[0] * (x - c * t))
126 * self.xp.sin(self.xp.pi * freq[1] * (y - c * t))
127 * self.xp.sin(self.xp.pi * freq[2] * (z - c * t))
128 )
130 return sol