Coverage for pySDC/projects/DAE/problems/simple_DAE.py: 95%
59 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-29 09:02 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-29 09:02 +0000
1import warnings
2import numpy as np
3from scipy.interpolate import interp1d
5from pySDC.projects.DAE.misc.ProblemDAE import ptype_dae
6from pySDC.implementations.datatype_classes.mesh import mesh
9class pendulum_2d(ptype_dae):
10 r"""
11 Example implementing the well known 2D pendulum as a first order differential-algebraic equation (DAE) of index 3.
12 The DAE system is given by the equations
14 .. math::
15 \frac{dp}{dt} = u,
17 .. math::
18 \frac{dq}{dt} = v,
20 .. math::
21 m\frac{du}{dt} = -p \lambda,
23 .. math::
24 m\frac{dv}{dt} = -q \lambda - g,
26 .. math::
27 0 = p^2 + q^2 - l^2
29 for :math:`l=1` and :math:`m=1`. The pendulum is used in most introductory literature on DAEs, for example on page 8
30 of [1]_.
32 Parameters
33 ----------
34 nvars : int
35 Number of unknowns of the system of DAEs.
36 newton_tol : float
37 Tolerance for Newton solver.
39 Attributes
40 ----------
41 t_end: float
42 The end time at which the reference solution is determined.
44 References
45 ----------
46 .. [1] E. Hairer, C. Lubich, M. Roche. The numerical solution of differential-algebraic systems by Runge-Kutta methods.
47 Lect. Notes Math. (1989).
48 """
50 def __init__(self, newton_tol):
51 """Initialization routine"""
52 super().__init__(nvars=5, newton_tol=newton_tol)
53 # load reference solution
54 # data file must be generated and stored under misc/data and self.t_end = t[-1]
55 # data = np.load(r'pySDC/projects/DAE/misc/data/pendulum.npy')
56 # t = data[:, 0]
57 # solution = data[:, 1:]
58 # self.u_ref = interp1d(t, solution, kind='cubic', axis=0, fill_value='extrapolate')
59 self.t_end = 0.0
61 def eval_f(self, u, du, t):
62 r"""
63 Routine to evaluate the implicit representation of the problem, i.e., :math:`F(u, u', t)`.
65 Parameters
66 ----------
67 u : dtype_u
68 Current values of the numerical solution at time t.
69 du : dtype_u
70 Current values of the derivative of the numerical solution at time t.
71 t : float
72 Current time of the numerical solution.
74 Returns
75 -------
76 f : dtype_f
77 Current value of the right-hand side of f (which includes five components).
78 """
79 g = 9.8
80 # The last element of u is a Lagrange multiplier. Not sure if this needs to be time dependent, but must model the
81 # weight somehow
82 f = self.dtype_f(self.init)
83 f.diff[:4] = (
84 du.diff[0] - u.diff[2],
85 du.diff[1] - u.diff[3],
86 du.diff[2] + u.alg[0] * u.diff[0],
87 du.diff[3] + u.alg[0] * u.diff[1] + g,
88 )
89 f.alg[0] = u.diff[0] ** 2 + u.diff[1] ** 2 - 1
90 self.work_counters['rhs']()
91 return f
93 def u_exact(self, t):
94 """
95 Approximation of the exact solution generated by spline interpolation of an extremely accurate numerical reference solution.
97 Parameters
98 ----------
99 t : float
100 The time of the reference solution.
102 Returns
103 -------
104 me : dtype_u
105 The reference solution as mesh object. It contains fixed initial conditions at initial time.
106 """
107 me = self.dtype_u(self.init)
108 if t == 0:
109 me.diff[:4] = (-1, 0, 0, 0)
110 me.alg[0] = 0
111 elif t < self.t_end:
112 u_ref = self.u_ref(t)
113 me.diff[:4] = u_ref[:4]
114 me.alg[0] = u_ref[5]
115 else:
116 self.logger.warning("Requested time exceeds domain of the reference solution. Returning zero.")
117 me.diff[:4] = (0, 0, 0, 0)
118 me.alg[0] = 0
119 return me
122class simple_dae_1(ptype_dae):
123 r"""
124 Example implementing a smooth linear index-2 differential-algebraic equation (DAE) with known analytical solution.
125 The DAE system is given by
127 .. math::
128 \frac{d u_1 (t)}{dt} = (\alpha - \frac{1}{2 - t}) u_1 (t) + (2-t) \alpha z (t) + \frac{3 - t}{2 - t},
130 .. math::
131 \frac{d u_2 (t)}{dt} = \frac{1 - \alpha}{t - 2} u_1 (t) - u_2 (t) + (\alpha - 1) z (t) + 2 e^{t},
133 .. math::
134 0 = (t + 2) u_1 (t) + (t^{2} - 4) u_2 (t) - (t^{2} + t - 2) e^{t}.
136 The exact solution of this system is
138 .. math::
139 u_1 (t) = u_2 (t) = e^{t},
141 .. math::
142 z (t) = -\frac{e^{t}}{2 - t}.
144 This example is commonly used to test that numerical implementations are functioning correctly. See, for example,
145 page 267 of [1]_.
147 Parameters
148 ----------
149 nvars : int
150 Number of unknowns of the system of DAEs.
151 newton_tol : float
152 Tolerance for Newton solver.
154 References
155 ----------
156 .. [1] U. Ascher, L. R. Petzold. Computer method for ordinary differential equations and differential-algebraic
157 equations. Society for Industrial and Applied Mathematics (1998).
158 """
160 def __init__(self, newton_tol=1e-10):
161 """Initialization routine"""
162 super().__init__(nvars=3, newton_tol=newton_tol)
164 def eval_f(self, u, du, t):
165 r"""
166 Routine to evaluate the implicit representation of the problem, i.e., :math:`F(u, u', t)`.
168 Parameters
169 ----------
170 u : dtype_u
171 Current values of the numerical solution at time t.
172 du : dtype_u
173 Current values of the derivative of the numerical solution at time t.
174 t : float
175 Current time of the numerical solution.
177 Returns
178 -------
179 f : dtype_f
180 Current value of the right-hand side of f (which includes three components).
181 """
182 # Smooth index-2 DAE pg. 267 Ascher and Petzold (also the first example in KDC Minion paper)
183 a = 10.0
184 f = self.dtype_f(self.init)
186 f.diff[:2] = (
187 -du.diff[0] + (a - 1 / (2 - t)) * u.diff[0] + (2 - t) * a * u.alg[0] + (3 - t) / (2 - t) * np.exp(t),
188 -du.diff[1] + (1 - a) / (t - 2) * u.diff[0] - u.diff[1] + (a - 1) * u.alg[0] + 2 * np.exp(t),
189 )
190 f.alg[0] = (t + 2) * u.diff[0] + (t**2 - 4) * u.diff[1] - (t**2 + t - 2) * np.exp(t)
191 self.work_counters['rhs']()
192 return f
194 def u_exact(self, t):
195 """
196 Routine for the exact solution.
198 Parameters
199 ----------
200 t : float
201 The time of the reference solution.
203 Returns
204 -------
205 me : dtype_u
206 The reference solution as mesh object containing three components.
207 """
208 me = self.dtype_u(self.init)
209 me.diff[:2] = (np.exp(t), np.exp(t))
210 me.alg[0] = -np.exp(t) / (2 - t)
211 return me
214class problematic_f(ptype_dae):
215 r"""
216 Standard example of a very simple fully implicit index-2 differential algebraic equation (DAE) that is not
217 numerically solvable for certain choices of the parameter :math:`\eta`. The DAE system is given by
219 .. math::
220 \frac{d y(t)}{dt} + \eta t \frac{d z(t)}{dt} + (1 + \eta) z (t) = g (t).
222 .. math::
223 y (t) + \eta t z (t) = f(t),
225 See, for example, page 264 of [1]_.
227 Parameters
228 ----------
229 nvars : int
230 Number of unknowns of the system of DAEs.
231 newton_tol : float
232 Tolerance for Newton solver.
234 Attributes
235 ----------
236 eta : float
237 Specific parameter of the problem.
239 References
240 ----------
241 .. [1] U. Ascher, L. R. Petzold. Computer method for ordinary differential equations and differential-algebraic
242 equations. Society for Industrial and Applied Mathematics (1998).
243 """
245 dtype_u = mesh
246 dtype_f = mesh
248 def __init__(self, newton_tol, eta=1):
249 """Initialization routine"""
250 super().__init__(nvars=2, newton_tol=newton_tol)
251 self._makeAttributeAndRegister('eta', localVars=locals())
253 def eval_f(self, u, du, t):
254 r"""
255 Routine to evaluate the implicit representation of the problem, i.e., :math:`F(u, u', t)`.
257 Parameters
258 ----------
259 u : dtype_u
260 Current values of the numerical solution at time t.
261 du : dtype_u
262 Current values of the derivative of the numerical solution at time t.
263 t : float
264 Current time of the numerical solution.
266 Returns
267 -------
268 f : dtype_f
269 Current value of the right-hand side of f (which includes two components).
270 """
271 f = self.dtype_f(self.init)
272 f[:] = (
273 u[0] + self.eta * t * u[1] - np.sin(t),
274 du[0] + self.eta * t * du[1] + (1 + self.eta) * u[1] - np.cos(t),
275 )
276 self.work_counters['rhs']()
277 return f
279 def u_exact(self, t):
280 """
281 Routine for the exact solution.
283 Parameters
284 ----------
285 t : float
286 The time of the reference solution.
288 Returns
289 -------
290 me : dtype_u
291 The reference solution as mesh object containing two components.
292 """
293 me = self.dtype_u(self.init)
294 me[:] = (np.sin(t), 0)
295 return me