Skip to content

Commit c4a1b1c

Browse files
authored
Adding solvers for quick experiments (#21)
* TL: added first Dahlquist and NonLinear solvers * TL: adapted fSolve to generic uShape * TL: minor details * TL: still trying stuff * TL: small testing on generic solver * TL: almost there ... * TL: first working version * TL: finally done ! * TL: added specialized nodeSolve for BE generic solver * TL: setup new structure * TL: added ProtheroRobinson DiffOperator * TL: refactoring and some documentation * TL: implemented tests for dahlquist solvers * TL: added tests for diffops * TL: almost done with tests * TL: finalized tests * TL: python version rollout * TL: started working on docs * TL: documentation update * TL: finalized docstrings for new modules * TL: minor debuging * TL: finalized devdocs * TL: doc update * TL: finalized advanced tutorials * TL: additional note on tutorial * TL: regenerated notebooks * TL: beautifying * TL: regenerate notebooks * TL: trying a small update * TL: minor change * TL: solved most of thomas's comments * TL: improved devdoc on DiffOp * TL: added imex stability scripts for thomas
1 parent 43dd0b6 commit c4a1b1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+4910
-303
lines changed

.github/workflows/ci_pipeline.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
python: ['3.9', '3.10', '3.11', '3.12', '3.13']
14+
python: ['3.10', '3.11', '3.12', '3.13', '3.14']
1515
defaults:
1616
run:
1717
shell: bash -l {0}
@@ -35,7 +35,7 @@ jobs:
3535
./test.sh
3636
- name: Upload coverage reports to Codecov
3737
uses: codecov/codecov-action@v4
38-
if: github.repository_owner == 'Parallel-in-Time' && matrix.python == '3.11'
38+
if: github.repository_owner == 'Parallel-in-Time' && matrix.python == '3.13'
3939
with:
4040
flags: smart-tests
4141
verbose: true
@@ -47,10 +47,10 @@ jobs:
4747

4848
steps:
4949
- uses: actions/checkout@v3
50-
- name: Set up Python 3.11
50+
- name: Set up Python 3.13
5151
uses: actions/setup-python@v3
5252
with:
53-
python-version: "3.11"
53+
python-version: "3.13"
5454
- name: Install dependencies
5555
run: |
5656
python -m pip install --upgrade pip

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ $$
3131

3232
and many different **lower-triangular** approximations of the $Q$ matrix, named $Q_\Delta$,
3333
which are key elements for Spectral Deferred Correction (SDC), or more general Iterated Runge-Kutta Methods.
34+
It also contains **generic time-integration solvers** based on $Q$ and $Q_\Delta$ coefficients,
35+
that can be used for quick testing and experiments.
3436

3537
[![DOI](https://zenodo.org/badge/804826743.svg)](https://zenodo.org/doi/10.5281/zenodo.11956478)
3638

@@ -78,3 +80,8 @@ and the current [Development Roadmap](https://qmat.readthedocs.io/en/latest/devd
7880
- Issues Tracker : https://github.com/Parallel-in-Time/qmat/issues
7981
- Q&A : https://github.com/Parallel-in-Time/qmat/discussions/categories/q-a
8082
- Project Proposals : https://github.com/Parallel-in-Time/qmat/discussions/categories/project-proposals
83+
84+
## Developers
85+
86+
- [Thibaut Lunet](https://github.com/tlunet)
87+
- [Thomas Saupe (né Baumann)](https://github.com/brownbaerchen)

docs/SECURITY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ While we recommend the use of the latest version, below is the list of the curre
1212

1313
## Reporting a Vulnerability
1414

15-
If you see any vulnerability with this package, please open an
15+
If you see any vulnerability with this package, please open an
1616
[issue on the Github interface ...](https://github.com/Parallel-in-Time/qmat/issues),
17-
so that is can be solved as quickly as possible by the developing community.
17+
so that is can be solved as quickly as possible by our developing community.

docs/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# -- Project information -----------------------------------------------------
2121

2222
project = 'QMat Package'
23-
copyright = '2024 PinT Community'
23+
copyright = '2025 PinT Community'
2424
author = 'PinT Community'
2525

2626
# The short X.Y version
@@ -72,7 +72,7 @@
7272
autoapi_dirs = ['../qmat']
7373
autoapi_file_patterns = ['*.py']
7474
autoapi_options = [
75-
'members', 'undoc-members',
75+
'members', 'undoc-members',
7676
'show-inheritance-diagram',
7777
'show-module-summary',
7878
]
@@ -162,5 +162,5 @@
162162
# -- Options for nbsphinx galleries
163163
# Using _images/ is a hack to get relocated images which have been included in the pages
164164
nbsphinx_thumbnails = {
165-
165+
166166
}

docs/contributing.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,19 @@ Current coverage is at 100%, so no untested line will be accepted 😇.
2626
2727
Chosen merge strategy is to squash commits $\Rightarrow$ you don't have to care about the number of commit included in your PR, so don't be scare of making mistakes before your PR is accepted 😉
2828

29-
> 🔔 Once your PR is accepted, please delete this branch from your fork and synchronize your `main` branch. When creating a new development branch later, ensure that you start from an up-to-date `main` branch of your fork.
29+
> 🔔 Once your PR is accepted, please delete this branch from your fork and synchronize your `main` branch. When creating a new development branch later, ensure that you start from an up-to-date `main` branch of your fork.
3030
3131
In case you are interested in contributing but don't have any idea on what, checkout out current [development roadmap 🎯](./devdoc/roadmap.md) and [project proposals 🎓](https://github.com/Parallel-in-Time/qmat/discussions/categories/project-proposals)
3232

3333
## Base recipes
3434

35-
_A few base memo on how to develop this package ..._
35+
_Some memos on how to develop this package ..._
3636

37-
- [General code structure](./devdoc/structure.md)
37+
- [Code structure](./devdoc/structure.md)
3838
- [Add a Runge-Kutta scheme](./devdoc/addRK.md)
39+
- [Add a playground](./devdoc/addPlayground.md)
40+
- [Add a differential operator](./devdoc/addDiffOp.md)
41+
- [Add a $\phi$-based time-integrator](./devdoc/addPhiIntegrator.md)
3942
- [Testing your changes](./devdoc/testing.md)
4043
- [Update this documentation](./devdoc/updateDoc.md)
4144
- [Version update pipeline](./devdoc/versionUpdate.md)
@@ -47,6 +50,9 @@ _A few base memo on how to develop this package ..._
4750
4851
devdoc/structure
4952
devdoc/addRK
53+
devdoc/addPlayground
54+
devdoc/addDiffOp
55+
devdoc/addPhiIntegrator
5056
devdoc/testing
5157
devdoc/updateDoc
5258
devdoc/versionUpdate

docs/devdoc/addDiffOp.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Add a differential operator
2+
3+
📜 _Solvers implemented in {py:mod}`qmat.solvers.generic` can be used_
4+
_with other {py:class}`DiffOp <qmat.solvers.generic.DiffOp>` classes_
5+
_than those implemented in {py:mod}`qmat.solvers.generic.diffops`._
6+
7+
To add a new one, implement it at the end of the `diffops.py` module,
8+
using the following template :
9+
10+
```python
11+
@registerDiffOp
12+
class Yoodlidoo(DiffOp):
13+
r"""
14+
Base description, in particular its equation :
15+
16+
.. math::
17+
18+
\frac{du}{dt} = ...
19+
20+
And some parameters description ...
21+
"""
22+
def __init__(self, params="value"):
23+
# use some initialization parameters
24+
u0 = ... # define your initial vector
25+
super().__init__(u0)
26+
27+
def evalF(self, u, t, out:np.ndarray):
28+
r"""
29+
Evaluate :math:`f(u,t)` and store the result into `out`.
30+
31+
Parameters
32+
----------
33+
u : np.ndarray
34+
Input solution for the evaluation.
35+
t : float
36+
Time for the evaluation.
37+
out : np.ndarray
38+
Output array in which is stored the evaluation.
39+
"""
40+
out[:] = ... # put the result into out
41+
```
42+
43+
And that's all ! The `registerDiffOp` operator will automatically
44+
- add your class in the `DIFFOPS` dictionary to make it generically available
45+
- check if your class properly overrides the `evalF` function (import error if not)
46+
- add your class to the [CI tests](./testing.md)
47+
48+
> 📣 Per default, all `DiffOp` classes must be instantiable with default parameters
49+
> in order to run the tests (see the {py:func}`DiffOp.test <qmat.solvers.generic.DiffOp.test>`
50+
> class method). But you can change that by overriding the `test` class method and put your own
51+
> preset parameters for the test (checkout the
52+
> {py:func}`ProtheroRobinson <qmat.solvers.generic.diffops.ProtheroRobinson>` class for an example).
53+
54+
Finally, the `DiffOp` class implements a default `fSolve` method, that solves :
55+
56+
$$
57+
u - \alpha f(u, t) = rhs
58+
$$
59+
60+
for any given $\alpha, t, rhs$.
61+
It relies on generic non-linear root-finding solvers, namely `scipy.optimize.fsolve` for small problems
62+
and `scipy.optimize.newton_krylov` for large scale problems.
63+
You can also implement a more efficient approach tailored to your problem like this :
64+
65+
```python
66+
@registerDiffOp
67+
class Yoodlidoo(DiffOp):
68+
# ...
69+
70+
def fSolve(self, a:float, rhs:np.ndarray, t:float, out:np.ndarray):
71+
r"""
72+
Solve :math:`u-\alpha f(u,t)=rhs` for given :math:`u,t,rhs`,
73+
using `out` as initial guess and storing the final result into it.
74+
75+
Parameters
76+
----------
77+
a : float
78+
The :math:`\alpha` coefficient.
79+
rhs : np.ndarray
80+
The right hand side.
81+
t : float
82+
Time for the evaluation.
83+
out : np.ndarray
84+
Input-output array used as initial guess,
85+
in which is stored the solution.
86+
"""
87+
# TODO : your ultra-efficient implementation that will be
88+
# way better than a generic call of scipy.optimize.fsolve
89+
# or scipy.optimize.newton_krylov.
90+
out[:] = ...
91+
```
92+
93+
> 🔔 Note that `out` will be used as output for the solution,
94+
> but its input value can also be used as initial guess for any
95+
> iterative solver you may want to use.

docs/devdoc/addPhiIntegrator.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Add a $\phi$-based time-integrator
2+
3+
📜 _Additional time schemes can be added using the [$\phi$ formulation](../notebooks/14_phiIntegrator.ipynb)_
4+
_to test other variants of $Q_\Delta$-coefficients free Spectral Deferred Correction._
5+
_For that, you can implement a new {py:mod}`PhiSolver <qmat.solvers.generic.PhiSolver>` class in the {py:mod}`qmat.solvers.generic.integrators` module_.
6+
7+
Add your class at the end of the `qmat.solvers.generic.integrators.py` module using the following template :
8+
9+
```python
10+
class Phidlidoo(PhiSolver):
11+
r"""
12+
Base description, in particular its definition :
13+
14+
.. math::
15+
16+
\phi(u_0, u_1, ..., u_{m}, u_{m+1}) =
17+
...
18+
19+
And eventual parameters description ...
20+
"""
21+
22+
def evalPhi(self, uVals, fEvals, out, t0=0):
23+
m = len(uVals) - 1
24+
assert m > 0
25+
assert len(fEvals) in [m, m+1]
26+
27+
# TODO : integrators implementation
28+
```
29+
30+
The first assertions are not mandatory, but ensure that the `evalPhi` is properly evaluated.
31+
32+
> 📣 New `PhiSolver` classes are not automatically tested, so you'll have to write
33+
> some dedicated test for your new class in `tests.test_solvers.test_integrators.py`.
34+
> Checkout those already implemented for `ForwardEuler` and `BackwardEuler`.
35+
36+
As for the {py:class}`DiffOp <qmat.solvers.generic.DiffOp>` class,
37+
the {py:class}`PhiSolver <qmat.solvers.generic.PhiSolver>` implements a generic default
38+
`phiSolve` method, that you can override by a more efficient specialized approach.
39+
40+
> 💡 Note that the model above inherits the `__init__` constructor of the `PhiSolver` class,
41+
> so it can take any `DiffOp` class as parameter.
42+
> If your time-integrator is specialized for some kind of differential operators
43+
> (_e.g_ a semi-Lagrangian scheme for an advective problem),
44+
> then you probably need to override the `__init__` method in your class too.

docs/devdoc/addPlayground.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Add a playground
2+
3+
📜 _To add experimental scripts or usage examples, without testing everything : simply add your own **playground** in {py:mod}`qmat.playgrounds`._
4+
5+
1. create a folder with a _short & representative_ name, _e.g_ `yoodlidoo` (can also be your name for a personal playground),
6+
2. put your script(s) in it, and document them as much as necessary so **anyone else can understand and use your code**,
7+
3. create a `__init__.py` file in your playground folder with a short summary of your scripts in its docstring, _e.g_
8+
```python
9+
"""
10+
- :class:`script1` : trying some stuff.
11+
- :class:`script2` : yet another idea.
12+
"""
13+
```
14+
4. add the item line corresponding to your playground in `qmat.playgrounds.__init__.py`, _e.g_
15+
```python
16+
"""
17+
...
18+
19+
Current playgrounds
20+
-------------------
21+
22+
- ...
23+
- :class:`yoodlidoo` : some ideas to do stuff
24+
"""
25+
```
26+
5. open a pull request against the `main` branch of `qmat`.
27+
28+
> 💡 If you don't want your playground to be integrated into the main branch of`qmat` (no proper documentation, code always evolving, ...),
29+
> you can still add a **soft link to a playground in your fork** by modifying `qmat.playgrounds.__init__.py` :
30+
> ```python
31+
> """
32+
> ...
33+
>
34+
> Current playgrounds
35+
> -------------------
36+
>
37+
> - ...
38+
> - `{name} <https://github.com/{userName}/qmat/tree/{branch}/qmat/playgrounds/{name}>`_ : some ideas ...
39+
> """
40+
> ```
41+
> where `name` is your playground name, `userName` your GitHub username and `branch` the branch name on your fork you are working on
42+
> (**do not use the `main` branch of your fork** ⚠️)

0 commit comments

Comments
 (0)