Skip to content

Commit 4e6f105

Browse files
Implementation of events with signature event(t, y, yp). (#38)
1 parent fa9cf30 commit 4e6f105

File tree

13 files changed

+265
-89
lines changed

13 files changed

+265
-89
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
- name: Setup python
2525
uses: actions/setup-python@v5
2626
with:
27-
python-version: "3.8"
27+
python-version: "3.10"
2828
cache: "pip" # caching pip dependencies
2929

3030
- name: Install dependencies and scipy_dae

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# scipy_dae - solving differential algebraic equations (DAE's) and implicit differential equations (IDE's) in Python
1+
# scipy_dae - solving differential algebraic equations (DAEs) and implicit differential equations (IDEs) in Python
22

33
<p align="center">
44
<a href="https://github.com/JonasBreuling/scipy_dae/actions/workflows/main.yml/badge.svg"><img alt="Actions Status" src="https://github.com/JonasBreuling/scipy_dae/actions/workflows/main.yml/badge.svg"></a>
@@ -9,7 +9,7 @@
99
<a href="https://pypi.org/project/scipy_dae/"><img alt="PyPI" src="https://img.shields.io/pypi/v/scipy_dae"></a>
1010
</p>
1111

12-
Python implementation of solvers for differential algebraic equations (DAE's) and implicit differential equations (IDE's) that should be added to scipy one day.
12+
Python implementation of solvers for differential algebraic equations (DAEs) and implicit differential equations (IDEs) that should be added to scipy one day.
1313

1414
Currently, two different methods are implemented.
1515

@@ -111,11 +111,11 @@ plt.show()
111111

112112
More examples are given in the [examples](examples/) directory, which includes
113113

114-
* ordinary differential equations (ODE's)
114+
* ordinary differential equations (ODEs)
115115
* [Van der Pol oscillator](examples/odes/van_der_pol.py)
116116
* [Sparse brusselator](examples/odes/sparse_brusselator.py)
117117
* [Stiff SE(3) Cosserat rod](examples/odes/se3_cosserat_rod.py)
118-
* differential algebraic equations (DAE's)
118+
* differential algebraic equations (DAEs)
119119
* [Robertson problem (index 1)](examples/daes/robertson.py)
120120
* [Akzo Nobel problem (index 1)](examples/daes/akzo_nobel.py)
121121
* [Stiff transistor amplifier (index 1)](examples/daes/stiff_transistor_amplifier.py)
@@ -126,7 +126,7 @@ More examples are given in the [examples](examples/) directory, which includes
126126
* [Cartesian pendulum (index 3)](examples/daes/pendulum.py)
127127
* [Particle on circular track (index 3)](examples/daes/arevalo.py)
128128
* [Andrews' squeezer mechanism (index 3)](examples/daes/andrews.py)
129-
* implicit differential equations (IDE's)
129+
* implicit differential equations (IDEs)
130130
* [Weissinger's implicit equation](examples/ides/weissinger.py)
131131
* [Problem I.542 of E. Kamke](examples/ides/kamke.py)
132132
* [Jackiewicz' implicit equation](examples/ides/jackiewicz.py)
@@ -177,7 +177,7 @@ $$
177177
\end{aligned}
178178
$$
179179

180-
Since the implemented solvers are designed for index 1 DAE's we have to perform some sort of index reduction. Therefore, we transform the semi-explicit form into a general form as proposed by [Gear](https://doi.org/10.1137/0909004). The resulting index 1 system is given as
180+
Since the implemented solvers are designed for index 1 DAEs we have to perform some sort of index reduction. Therefore, we transform the semi-explicit form into a general form as proposed by [Gear](https://doi.org/10.1137/0909004). The resulting index 1 system is given as
181181

182182
$$
183183
\begin{aligned}
@@ -226,7 +226,7 @@ $$
226226
\end{aligned}
227227
$$
228228

229-
Since the implemented solvers are designed for index 1 DAE's we have to perform some sort of index reduction. Therefore, we use the [stabilized index 1 formulation of Hiller and Anantharaman](https://doi.org/10.1002/nme.1620320803). The resulting index 1 system is given as
229+
Since the implemented solvers are designed for index 1 DAEs we have to perform some sort of index reduction. Therefore, we use the [stabilized index 1 formulation of Hiller and Anantharaman](https://doi.org/10.1002/nme.1620320803). The resulting index 1 system is given as
230230

231231
$$
232232
\begin{aligned}

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ requires = ["meson-python>=0.16.0"]
44

55
[project]
66
name = "scipy_dae"
7-
version = "0.0.6"
7+
version = "0.0.8"
88
authors = [
99
{ name="Jonas Breuling", email="[email protected]" },
1010
]
11-
description = "Python implementation of solvers for differential algebraic equations (DAE's) and implicit differential equations (IDE's) that should be added to scipy one day."
11+
description = "Python implementation of solvers for differential algebraic equations (DAEs) and implicit differential equations (IDEs) that should be added to scipy one day."
1212
readme = "README.md"
1313
requires-python = ">=3.8"
1414
dependencies = [
15-
"numpy>=1.24.4",
16-
"scipy>=1.10.1",
15+
"numpy>=2.0.1",
16+
"scipy>=1.14.0",
1717
"matplotlib>=3.4.3",
1818
]
1919
classifiers = [

scipy_dae/integrate/_dae/base.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ def fun_wrapped(t, y, yp):
4646

4747
return fun_wrapped, y0, yp0
4848

49-
# TODO:
50-
# - check documentation
51-
# - add consistent initial conditions somehow
49+
5250
class DaeSolver:
5351
"""Base class for DAE solvers.
5452
@@ -102,17 +100,11 @@ class DaeSolver:
102100
y0 : array_like, shape (n,)
103101
Initial state.
104102
yp0 : array_like, shape (n,), optional
105-
Initial derivative. If the derivative is not given by the user, it is
106-
esimated using??? => TODO: See Petzold/ Shampine and coworkers how
107-
this is done.
103+
Initial derivative. It it is assumed that the value is consistent,
104+
i.e. f(t0, y0, yp0) = 0.
108105
t_bound : float
109106
Boundary time --- the integration won't continue beyond it. It also
110107
determines the direction of the integration.
111-
var_index : array_like, shape (n,), optional
112-
Differentiation index of the respective row of f(t, y, y') = 0.
113-
Depending on this index, the error estimates are scaled by the
114-
stepsize h**(index - 1) in order to ensure convergence.
115-
Default is None, which means all equations are differential equations.
116108
vectorized : bool
117109
Whether `fun` can be called in a vectorized fashion. Default is False.
118110
@@ -166,7 +158,7 @@ class DaeSolver:
166158
TOO_SMALL_STEP = "Required step size is less than spacing between numbers."
167159

168160
def __init__(self, fun, t0, y0, yp0, t_bound, rtol, atol,
169-
first_step=None, max_step=np.inf, vectorized=False,
161+
first_step=None, max_step=np.inf, vectorized=False,
170162
jac=None, jac_sparsity=None, support_complex=False):
171163
self.t_old = None
172164
self.t = t0
@@ -281,7 +273,7 @@ def jac_wrapped(t, y, yp):
281273
# lambda t, yp: self.fun_vectorized(t, y, yp),
282274
# t, yp, f, self.atol, self.jac_factor_yp, sparsity_yp)
283275

284-
# TODO: This choice is better but not optimal!
276+
# note: this choice is better but not optimal
285277
threshold = self.atol / self.rtol
286278
Jy, self.jac_factor_y = num_jac(
287279
lambda t, y: self.fun_vectorized(t, y, yp),
@@ -423,6 +415,7 @@ def _step_impl(self):
423415
def _dense_output_impl(self):
424416
raise NotImplementedError
425417

418+
426419
class DAEDenseOutput:
427420
"""Base class for local interpolant over step made by an ODE solver.
428421

scipy_dae/integrate/_dae/bdf.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,13 @@ class BDFDAE(DaeSolver):
152152
153153
It is generally recommended to provide the Jacobians rather than
154154
relying on a finite-difference approximation.
155-
# TODO: Adapt and test this.
156155
jac_sparsity : {None, array_like, sparse matrix}, optional
157156
Defines a sparsity structure of the Jacobian matrix for a
158157
finite-difference approximation. Its shape must be (n, n). This argument
159158
is ignored if `jac` is not `None`. If the Jacobian has only few non-zero
160159
elements in *each* row, providing the sparsity structure will greatly
161160
speed up the computations [4]_. A zero entry means that a corresponding
162161
element in the Jacobian is always zero. If None (default), the Jacobian
163-
# t_eval = np.concatenate((t, t + t1)) / 2
164-
t_eval = np.array([t0, *(t0 + 1e-3 + np.cumsum(np.diff(t)))])
165-
# t_eval = np.concatenate((t, t + t1, t + 2 * t1)) / 3
166162
is assumed to be dense.
167163
vectorized : bool, optional
168164
Whether `fun` can be called in a vectorized fashion. Default is False.
@@ -231,8 +227,9 @@ def __init__(self, fun, t0, y0, yp0, t_bound, max_step=np.inf,
231227
NDF_strategy="stability", **extraneous):
232228
warn_extraneous(extraneous)
233229
super().__init__(fun, t0, y0, yp0, t_bound, rtol, atol,
234-
first_step, max_step, vectorized, jac,
235-
jac_sparsity, support_complex=True)
230+
first_step=first_step, max_step=max_step,
231+
vectorized=vectorized, jac=jac,
232+
jac_sparsity=jac_sparsity, support_complex=True)
236233

237234
self.newton_tol = max(10 * EPS / rtol, min(0.03, rtol ** 0.5))
238235

scipy_dae/integrate/_dae/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from itertools import groupby
22
import numpy as np
3-
# TODO: use sparse QR when available in scipy
3+
# note: use sparse QR when available in scipy
44
from scipy.linalg import qr, solve_triangular
55
from scipy.integrate._ivp.common import norm, EPS
66
from scipy.optimize._numdiff import approx_derivative

0 commit comments

Comments
 (0)