IRKsome 2026.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. irksome-2026.0.0/IRKsome.egg-info/PKG-INFO +54 -0
  2. irksome-2026.0.0/IRKsome.egg-info/SOURCES.txt +85 -0
  3. irksome-2026.0.0/IRKsome.egg-info/dependency_links.txt +1 -0
  4. irksome-2026.0.0/IRKsome.egg-info/requires.txt +13 -0
  5. irksome-2026.0.0/IRKsome.egg-info/top_level.txt +1 -0
  6. irksome-2026.0.0/LICENSE +13 -0
  7. irksome-2026.0.0/PKG-INFO +54 -0
  8. irksome-2026.0.0/README.md +17 -0
  9. irksome-2026.0.0/irksome/__init__.py +122 -0
  10. irksome-2026.0.0/irksome/backend.py +129 -0
  11. irksome-2026.0.0/irksome/backends/__init__.py +0 -0
  12. irksome-2026.0.0/irksome/backends/dolfinx.py +184 -0
  13. irksome-2026.0.0/irksome/backends/firedrake.py +139 -0
  14. irksome-2026.0.0/irksome/base_time_stepper.py +252 -0
  15. irksome-2026.0.0/irksome/bcs.py +52 -0
  16. irksome-2026.0.0/irksome/constant.py +21 -0
  17. irksome-2026.0.0/irksome/dirk_stepper.py +224 -0
  18. irksome-2026.0.0/irksome/discontinuous_galerkin_stepper.py +309 -0
  19. irksome-2026.0.0/irksome/explicit_stepper.py +21 -0
  20. irksome-2026.0.0/irksome/galerkin_stepper.py +440 -0
  21. irksome-2026.0.0/irksome/imex.py +647 -0
  22. irksome-2026.0.0/irksome/integrated_lagrange.py +39 -0
  23. irksome-2026.0.0/irksome/labeling.py +174 -0
  24. irksome-2026.0.0/irksome/multistep.py +182 -0
  25. irksome-2026.0.0/irksome/nystrom_dirk_stepper.py +281 -0
  26. irksome-2026.0.0/irksome/nystrom_stepper.py +222 -0
  27. irksome-2026.0.0/irksome/pc.py +170 -0
  28. irksome-2026.0.0/irksome/scheme.py +186 -0
  29. irksome-2026.0.0/irksome/stage_derivative.py +433 -0
  30. irksome-2026.0.0/irksome/stage_value.py +344 -0
  31. irksome-2026.0.0/irksome/stepper.py +236 -0
  32. irksome-2026.0.0/irksome/tableaux/ButcherTableaux.py +261 -0
  33. irksome-2026.0.0/irksome/tableaux/ars_dirk_imex_tableaux.py +111 -0
  34. irksome-2026.0.0/irksome/tableaux/dirk_imex_tableaux.py +58 -0
  35. irksome-2026.0.0/irksome/tableaux/multistep_tableaux.py +126 -0
  36. irksome-2026.0.0/irksome/tableaux/pep_explicit_rk.py +70 -0
  37. irksome-2026.0.0/irksome/tableaux/sspk_tableau.py +85 -0
  38. irksome-2026.0.0/irksome/tableaux/wso_dirk_tableaux.py +183 -0
  39. irksome-2026.0.0/irksome/tools.py +171 -0
  40. irksome-2026.0.0/irksome/ufl/__init__.py +0 -0
  41. irksome-2026.0.0/irksome/ufl/deriv.py +176 -0
  42. irksome-2026.0.0/irksome/ufl/estimate_degrees.py +194 -0
  43. irksome-2026.0.0/irksome/ufl/lag.py +12 -0
  44. irksome-2026.0.0/irksome/ufl/manipulation.py +277 -0
  45. irksome-2026.0.0/pyproject.toml +37 -0
  46. irksome-2026.0.0/setup.cfg +10 -0
  47. irksome-2026.0.0/tests/test_accuracy.py +133 -0
  48. irksome-2026.0.0/tests/test_adaptive.py +225 -0
  49. irksome-2026.0.0/tests/test_adjoint.py +59 -0
  50. irksome-2026.0.0/tests/test_appctx.py +20 -0
  51. irksome-2026.0.0/tests/test_base_kwargs.py +45 -0
  52. irksome-2026.0.0/tests/test_bern.py +240 -0
  53. irksome-2026.0.0/tests/test_bounds.py +371 -0
  54. irksome-2026.0.0/tests/test_butcher.py +64 -0
  55. irksome-2026.0.0/tests/test_collocation_eval.py +224 -0
  56. irksome-2026.0.0/tests/test_curl.py +60 -0
  57. irksome-2026.0.0/tests/test_dae.py +151 -0
  58. irksome-2026.0.0/tests/test_degree_estimation.py +114 -0
  59. irksome-2026.0.0/tests/test_delta.py +135 -0
  60. irksome-2026.0.0/tests/test_differentiation.py +94 -0
  61. irksome-2026.0.0/tests/test_dirichletbc.py +65 -0
  62. irksome-2026.0.0/tests/test_dirk.py +289 -0
  63. irksome-2026.0.0/tests/test_disc_galerkin.py +153 -0
  64. irksome-2026.0.0/tests/test_equationbc.py +167 -0
  65. irksome-2026.0.0/tests/test_explicit.py +76 -0
  66. irksome-2026.0.0/tests/test_galerkin.py +371 -0
  67. irksome-2026.0.0/tests/test_has_nonlinear_time_derivative.py +80 -0
  68. irksome-2026.0.0/tests/test_imex.py +258 -0
  69. irksome-2026.0.0/tests/test_inhomogbc.py +55 -0
  70. irksome-2026.0.0/tests/test_lag.py +56 -0
  71. irksome-2026.0.0/tests/test_mass_conservation.py +163 -0
  72. irksome-2026.0.0/tests/test_multistep.py +325 -0
  73. irksome-2026.0.0/tests/test_multistep_tableau.py +48 -0
  74. irksome-2026.0.0/tests/test_nystrom.py +282 -0
  75. irksome-2026.0.0/tests/test_nystrom_pc.py +100 -0
  76. irksome-2026.0.0/tests/test_odevsdae.py +57 -0
  77. irksome-2026.0.0/tests/test_pc.py +414 -0
  78. irksome-2026.0.0/tests/test_rtcf.py +59 -0
  79. irksome-2026.0.0/tests/test_split.py +207 -0
  80. irksome-2026.0.0/tests/test_stage_value_init.py +53 -0
  81. irksome-2026.0.0/tests/test_stokes.py +212 -0
  82. irksome-2026.0.0/tests/test_subdomainbc.py +104 -0
  83. irksome-2026.0.0/tests/test_tensor_fs.py +28 -0
  84. irksome-2026.0.0/tests/test_time_form_splitting.py +154 -0
  85. irksome-2026.0.0/tests/test_vecbc.py +62 -0
  86. irksome-2026.0.0/tests/test_wave_energy.py +79 -0
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: IRKsome
3
+ Version: 2026.0.0
4
+ Summary: A library for fully implicit Runge-Kutta methods in Firedrake
5
+ Author: Pablo Brubeck, Patrick E. Farrell, Scott P. MacLachlan
6
+ Author-email: "Robert C. Kirby" <Robert_Kirby@baylor.edu>
7
+ License: Irksome is free software: you can redistribute it and/or modify it under
8
+ the terms of the GNU Lesser General Public License as published by the
9
+ Free Software Foundation, either version 3 of the License, or (at your
10
+ option) any later version.
11
+
12
+ Irksome is distributed in the hope that it will be useful, but WITHOUT
13
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
+ License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with Irksome. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+
21
+ Project-URL: Homepage, https://www.firedrakeproject.org/Irksome
22
+ Project-URL: Repository, https://github.com/firedrakeproject/Irksome.git
23
+ Classifier: Programming Language :: Python
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: ci
27
+ Requires-Dist: flake8; extra == "ci"
28
+ Requires-Dist: pytest; extra == "ci"
29
+ Requires-Dist: vtk; extra == "ci"
30
+ Provides-Extra: dolfinx
31
+ Requires-Dist: scifem; extra == "dolfinx"
32
+ Requires-Dist: firedrake-fiat; extra == "dolfinx"
33
+ Provides-Extra: docs
34
+ Requires-Dist: sphinx; extra == "docs"
35
+ Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
36
+ Dynamic: license-file
37
+
38
+ # Irksome
39
+
40
+ This package works with Firedrake to generate Runge-Kutta methods from a semi-discrete UFL form. We have added a UFL symbol for time derivatives and can produce UFL for the fully discrete method from a semi-discrete form and a Butcher tableau. Several such tableaux are available, and some utility functions for time-stepping and adaptive time-stepping provided the tableau has an embedded lower-order method.
41
+
42
+ A long-standing critique of fully implicit RK methods, especially for PDE, is that they require a very large algebraic solve for all stages concurrently. However, we can use Firedrake's solver infrastructure to address this issue, and also recover most of the comparative efficiency of DIRK or explicit methods.
43
+
44
+ The core of Irksome is based on UFL manipulation and so should be adaptable to work with FEniCS or other UFL-based packages, but the current version works only with Firedrake. As such, it requires a working Irksome installation.
45
+
46
+ To install Irksome you need a working Firedrake installation (instructions can be found [here](https://www.firedrakeproject.org/install.html)) and then Irksome can be installed by running:
47
+ ```
48
+ $ pip install --src . --editable git+https://github.com/firedrakeproject/Irksome.git#egg=Irksome
49
+ ```
50
+ or, equivalently:
51
+ ```
52
+ $ git clone https://github.com/firedrakeproject/Irksome.git
53
+ $ pip install --editable ./Irksome
54
+ ```
@@ -0,0 +1,85 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ IRKsome.egg-info/PKG-INFO
6
+ IRKsome.egg-info/SOURCES.txt
7
+ IRKsome.egg-info/dependency_links.txt
8
+ IRKsome.egg-info/requires.txt
9
+ IRKsome.egg-info/top_level.txt
10
+ irksome/__init__.py
11
+ irksome/backend.py
12
+ irksome/base_time_stepper.py
13
+ irksome/bcs.py
14
+ irksome/constant.py
15
+ irksome/dirk_stepper.py
16
+ irksome/discontinuous_galerkin_stepper.py
17
+ irksome/explicit_stepper.py
18
+ irksome/galerkin_stepper.py
19
+ irksome/imex.py
20
+ irksome/integrated_lagrange.py
21
+ irksome/labeling.py
22
+ irksome/multistep.py
23
+ irksome/nystrom_dirk_stepper.py
24
+ irksome/nystrom_stepper.py
25
+ irksome/pc.py
26
+ irksome/scheme.py
27
+ irksome/stage_derivative.py
28
+ irksome/stage_value.py
29
+ irksome/stepper.py
30
+ irksome/tools.py
31
+ irksome/backends/__init__.py
32
+ irksome/backends/dolfinx.py
33
+ irksome/backends/firedrake.py
34
+ irksome/tableaux/ButcherTableaux.py
35
+ irksome/tableaux/ars_dirk_imex_tableaux.py
36
+ irksome/tableaux/dirk_imex_tableaux.py
37
+ irksome/tableaux/multistep_tableaux.py
38
+ irksome/tableaux/pep_explicit_rk.py
39
+ irksome/tableaux/sspk_tableau.py
40
+ irksome/tableaux/wso_dirk_tableaux.py
41
+ irksome/ufl/__init__.py
42
+ irksome/ufl/deriv.py
43
+ irksome/ufl/estimate_degrees.py
44
+ irksome/ufl/lag.py
45
+ irksome/ufl/manipulation.py
46
+ tests/test_accuracy.py
47
+ tests/test_adaptive.py
48
+ tests/test_adjoint.py
49
+ tests/test_appctx.py
50
+ tests/test_base_kwargs.py
51
+ tests/test_bern.py
52
+ tests/test_bounds.py
53
+ tests/test_butcher.py
54
+ tests/test_collocation_eval.py
55
+ tests/test_curl.py
56
+ tests/test_dae.py
57
+ tests/test_degree_estimation.py
58
+ tests/test_delta.py
59
+ tests/test_differentiation.py
60
+ tests/test_dirichletbc.py
61
+ tests/test_dirk.py
62
+ tests/test_disc_galerkin.py
63
+ tests/test_equationbc.py
64
+ tests/test_explicit.py
65
+ tests/test_galerkin.py
66
+ tests/test_has_nonlinear_time_derivative.py
67
+ tests/test_imex.py
68
+ tests/test_inhomogbc.py
69
+ tests/test_lag.py
70
+ tests/test_mass_conservation.py
71
+ tests/test_multistep.py
72
+ tests/test_multistep_tableau.py
73
+ tests/test_nystrom.py
74
+ tests/test_nystrom_pc.py
75
+ tests/test_odevsdae.py
76
+ tests/test_pc.py
77
+ tests/test_rtcf.py
78
+ tests/test_split.py
79
+ tests/test_stage_value_init.py
80
+ tests/test_stokes.py
81
+ tests/test_subdomainbc.py
82
+ tests/test_tensor_fs.py
83
+ tests/test_time_form_splitting.py
84
+ tests/test_vecbc.py
85
+ tests/test_wave_energy.py
@@ -0,0 +1,13 @@
1
+
2
+ [ci]
3
+ flake8
4
+ pytest
5
+ vtk
6
+
7
+ [docs]
8
+ sphinx
9
+ sphinxcontrib-bibtex
10
+
11
+ [dolfinx]
12
+ scifem
13
+ firedrake-fiat
@@ -0,0 +1 @@
1
+ irksome
@@ -0,0 +1,13 @@
1
+ Irksome is free software: you can redistribute it and/or modify it under
2
+ the terms of the GNU Lesser General Public License as published by the
3
+ Free Software Foundation, either version 3 of the License, or (at your
4
+ option) any later version.
5
+
6
+ Irksome is distributed in the hope that it will be useful, but WITHOUT
7
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
9
+ License for more details.
10
+
11
+ You should have received a copy of the GNU Lesser General Public
12
+ License along with Irksome. If not, see <http://www.gnu.org/licenses/>.
13
+
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: IRKsome
3
+ Version: 2026.0.0
4
+ Summary: A library for fully implicit Runge-Kutta methods in Firedrake
5
+ Author: Pablo Brubeck, Patrick E. Farrell, Scott P. MacLachlan
6
+ Author-email: "Robert C. Kirby" <Robert_Kirby@baylor.edu>
7
+ License: Irksome is free software: you can redistribute it and/or modify it under
8
+ the terms of the GNU Lesser General Public License as published by the
9
+ Free Software Foundation, either version 3 of the License, or (at your
10
+ option) any later version.
11
+
12
+ Irksome is distributed in the hope that it will be useful, but WITHOUT
13
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
+ License for more details.
16
+
17
+ You should have received a copy of the GNU Lesser General Public
18
+ License along with Irksome. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+
21
+ Project-URL: Homepage, https://www.firedrakeproject.org/Irksome
22
+ Project-URL: Repository, https://github.com/firedrakeproject/Irksome.git
23
+ Classifier: Programming Language :: Python
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: ci
27
+ Requires-Dist: flake8; extra == "ci"
28
+ Requires-Dist: pytest; extra == "ci"
29
+ Requires-Dist: vtk; extra == "ci"
30
+ Provides-Extra: dolfinx
31
+ Requires-Dist: scifem; extra == "dolfinx"
32
+ Requires-Dist: firedrake-fiat; extra == "dolfinx"
33
+ Provides-Extra: docs
34
+ Requires-Dist: sphinx; extra == "docs"
35
+ Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
36
+ Dynamic: license-file
37
+
38
+ # Irksome
39
+
40
+ This package works with Firedrake to generate Runge-Kutta methods from a semi-discrete UFL form. We have added a UFL symbol for time derivatives and can produce UFL for the fully discrete method from a semi-discrete form and a Butcher tableau. Several such tableaux are available, and some utility functions for time-stepping and adaptive time-stepping provided the tableau has an embedded lower-order method.
41
+
42
+ A long-standing critique of fully implicit RK methods, especially for PDE, is that they require a very large algebraic solve for all stages concurrently. However, we can use Firedrake's solver infrastructure to address this issue, and also recover most of the comparative efficiency of DIRK or explicit methods.
43
+
44
+ The core of Irksome is based on UFL manipulation and so should be adaptable to work with FEniCS or other UFL-based packages, but the current version works only with Firedrake. As such, it requires a working Irksome installation.
45
+
46
+ To install Irksome you need a working Firedrake installation (instructions can be found [here](https://www.firedrakeproject.org/install.html)) and then Irksome can be installed by running:
47
+ ```
48
+ $ pip install --src . --editable git+https://github.com/firedrakeproject/Irksome.git#egg=Irksome
49
+ ```
50
+ or, equivalently:
51
+ ```
52
+ $ git clone https://github.com/firedrakeproject/Irksome.git
53
+ $ pip install --editable ./Irksome
54
+ ```
@@ -0,0 +1,17 @@
1
+ # Irksome
2
+
3
+ This package works with Firedrake to generate Runge-Kutta methods from a semi-discrete UFL form. We have added a UFL symbol for time derivatives and can produce UFL for the fully discrete method from a semi-discrete form and a Butcher tableau. Several such tableaux are available, and some utility functions for time-stepping and adaptive time-stepping provided the tableau has an embedded lower-order method.
4
+
5
+ A long-standing critique of fully implicit RK methods, especially for PDE, is that they require a very large algebraic solve for all stages concurrently. However, we can use Firedrake's solver infrastructure to address this issue, and also recover most of the comparative efficiency of DIRK or explicit methods.
6
+
7
+ The core of Irksome is based on UFL manipulation and so should be adaptable to work with FEniCS or other UFL-based packages, but the current version works only with Firedrake. As such, it requires a working Irksome installation.
8
+
9
+ To install Irksome you need a working Firedrake installation (instructions can be found [here](https://www.firedrakeproject.org/install.html)) and then Irksome can be installed by running:
10
+ ```
11
+ $ pip install --src . --editable git+https://github.com/firedrakeproject/Irksome.git#egg=Irksome
12
+ ```
13
+ or, equivalently:
14
+ ```
15
+ $ git clone https://github.com/firedrakeproject/Irksome.git
16
+ $ pip install --editable ./Irksome
17
+ ```
@@ -0,0 +1,122 @@
1
+ from .tableaux.ButcherTableaux import (
2
+ Alexander,
3
+ BackwardEuler,
4
+ GaussLegendre,
5
+ LobattoIIIA,
6
+ LobattoIIIC,
7
+ PareschiRusso,
8
+ QinZhang,
9
+ RadauIIA,
10
+ )
11
+ from .tableaux.multistep_tableaux import (
12
+ BDF,
13
+ AdamsBashforth,
14
+ AdamsMoulton,
15
+ )
16
+ from .tableaux.pep_explicit_rk import PEPRK
17
+ from .ufl.deriv import Dt, expand_time_derivatives, check_irksome_import_order
18
+ from .ufl.lag import lag
19
+
20
+ check_irksome_import_order()
21
+
22
+ from .tableaux.dirk_imex_tableaux import DIRK_IMEX
23
+ from .tableaux.ars_dirk_imex_tableaux import ARS_DIRK_IMEX
24
+ from .tableaux.sspk_tableau import SSPK_DIRK_IMEX, SSPButcherTableau
25
+ from .tableaux.multistep_tableaux import MultistepTableau
26
+
27
+ from .constant import MeshConstant
28
+ from .tableaux.wso_dirk_tableaux import WSODIRK
29
+ from .scheme import create_time_quadrature
30
+ from .scheme import ContinuousPetrovGalerkinScheme, DiscontinuousGalerkinScheme
31
+ from .scheme import GalerkinCollocationScheme, DiscontinuousGalerkinCollocationScheme
32
+ from .bcs import BoundsConstrainedDirichletBC
33
+ from .dirk_stepper import DIRKTimeStepper
34
+ from .imex import RadauIIAIMEXMethod, DIRKIMEXMethod
35
+ from .stage_derivative import getForm
36
+ from .nystrom_dirk_stepper import DIRKNystromTimeStepper, ExplicitNystromTimeStepper
37
+ from .nystrom_stepper import (
38
+ StageDerivativeNystromTimeStepper,
39
+ ClassicNystrom4Tableau,
40
+ )
41
+ from .stage_value import StageValueTimeStepper
42
+
43
+ from .multistep import MultistepTimeStepper
44
+
45
+
46
+ __all__ = [
47
+ "AdamsBashforth",
48
+ "AdamsMoulton",
49
+ "Alexander",
50
+ "ARS_DIRK_IMEX",
51
+ "BackwardEuler",
52
+ "BDF",
53
+ "create_time_quadrature",
54
+ "DIRK_IMEX",
55
+ "DiscontinuousGalerkinCollocationScheme",
56
+ "Dt",
57
+ "expand_time_derivatives",
58
+ "GalerkinCollocationScheme",
59
+ "GaussLegendre",
60
+ "lag",
61
+ "LobattoIIIA",
62
+ "LobattoIIIC",
63
+ "MeshConstant",
64
+ "MultistepTableau",
65
+ "PareschiRusso",
66
+ "PEPRK",
67
+ "QinZhang",
68
+ "RadauIIA",
69
+ "SSPButcherTableau",
70
+ "SSPK_DIRK_IMEX",
71
+ "WSODIRK",
72
+ "DIRKTimeStepper",
73
+ "BoundsConstrainedDirichletBC",
74
+ "getForm",
75
+ "RadauIIAIMEXMethod",
76
+ "DIRKIMEXMethod",
77
+ "DIRKNystromTimeStepper",
78
+ "ExplicitNystromTimeStepper",
79
+ "StageDerivativeNystromTimeStepper",
80
+ "ClassicNystrom4Tableau",
81
+ "StageValueTimeStepper",
82
+ "ContinuousPetrovGalerkinTimeStepper",
83
+ "DiscontinuousGalerkinTimeStepper",
84
+ "MultistepTimeStepper",
85
+ ]
86
+
87
+
88
+ try:
89
+ import importlib
90
+
91
+ importlib.import_module("firedrake")
92
+ from .labeling import TimeQuadratureLabel
93
+ from .discontinuous_galerkin_stepper import DiscontinuousGalerkinTimeStepper
94
+ from .galerkin_stepper import ContinuousPetrovGalerkinTimeStepper
95
+
96
+ from .pc import (
97
+ ClinesBase,
98
+ ClinesLD,
99
+ NystromAuxiliaryOperatorPC,
100
+ RanaBase,
101
+ RanaDU,
102
+ RanaLD,
103
+ IRKAuxiliaryOperatorPC,
104
+ )
105
+ from .stepper import TimeStepper
106
+
107
+ __all__ += [
108
+ "TimeQuadratureLabel",
109
+ "DiscontinuousGalerkinScheme",
110
+ "ContinuousPetrovGalerkinScheme",
111
+ "ClinesBase",
112
+ "ClinesLD",
113
+ "NystromAuxiliaryOperatorPC",
114
+ "RanaBase",
115
+ "RanaDU",
116
+ "RanaLD",
117
+ "IRKAuxiliaryOperatorPC",
118
+ "TimeStepper",
119
+ ]
120
+
121
+ except ModuleNotFoundError:
122
+ pass
@@ -0,0 +1,129 @@
1
+ from typing import Protocol, Any, Sequence
2
+ import ufl
3
+ from importlib import import_module
4
+ import types
5
+
6
+
7
+ class Backend(Protocol):
8
+ def get_function_space(self, V: ufl.Coefficient) -> ufl.FunctionSpace:
9
+ """Get a function space from the backend"""
10
+
11
+ def extract_bcs(bcs: Any) -> tuple[Any]:
12
+ """Extract boundary conditions"""
13
+
14
+ class Function:
15
+ ...
16
+
17
+ class DirichletBC:
18
+ ...
19
+
20
+ def get_stages(self, V: ufl.FunctionSpace, num_stages: int) -> ufl.Coefficient:
21
+ """
22
+ Given a function space for a single time-step, get a duplicate of this space,
23
+ repeated `num_stages` times.
24
+
25
+ Args:
26
+ V: Space for single step
27
+ num_stages: Number of stages
28
+
29
+ Returns:
30
+ A coefficient in the new function space
31
+ """
32
+
33
+ class Constant:
34
+ """MeshLess constant class"""
35
+
36
+ class MeshConstant:
37
+ def __init__(self, msh: ufl.Mesh):
38
+ """Initialize a mesh constant over a domain"""
39
+
40
+ def Constant(self, val: float = 0.0):
41
+ """Generate a constant in the backend language with a specific value"""
42
+
43
+ def ConstantOrZero(
44
+ x: float | complex, MC: MeshConstant | None = None
45
+ ) -> ufl.core.expr.Expr:
46
+ """
47
+ Create a constant with backend class if MeshConstant is not supplied.
48
+ Create UFL zero if `x` is sufficiently small
49
+ """
50
+
51
+ def get_mesh_constant(MC: MeshConstant | None) -> ufl.core.expr.Expr:
52
+ """Get a backend class to construct a mesh constant from"""
53
+
54
+ def TestFunction(space: ufl.FunctionSpace, part: int | None = None) -> ufl.Argument:
55
+ """Return a test-function that can be used by forms in the backend."""
56
+
57
+ def TrialFunction(
58
+ space: ufl.FunctionSpace, part: int | None = None
59
+ ) -> ufl.Argument:
60
+ """Return a trial-function that can be used by forms in the backend."""
61
+
62
+ def create_variational_problem(
63
+ F: ufl.Form,
64
+ u: ufl.Coefficient,
65
+ bcs: DirichletBC | Sequence | None = None,
66
+ **kwargs,
67
+ ) -> Any:
68
+ """Create a variational problem in the backend language."""
69
+
70
+ def create_variational_solver(
71
+ problem: Any,
72
+ solver_parameters: dict | None = None,
73
+ **kwargs,
74
+ ):
75
+ """Create a variational solver in the backend language."""
76
+
77
+ def get_stage_spaces(V: ufl.FunctionSpace, num_stages: int) -> ufl.FunctionSpace:
78
+ """Create a stage space with M number of components."""
79
+
80
+ def norm(
81
+ v: ufl.core.expr.Expr, norm_type: str = "L2", mesh: ufl.Mesh | None = None
82
+ ) -> float:
83
+ """Compute the norm of a function in the backend language."""
84
+
85
+ def assemble(expr: ufl.core.expr.Expr) -> Any:
86
+ """Assemble a UFL expression in the backend language."""
87
+
88
+ def derivative(
89
+ form: ufl.Form,
90
+ u: ufl.Coefficient,
91
+ du: ufl.Argument | None = None,
92
+ coefficient_derivatives: dict | None = None,
93
+ ) -> ufl.Form:
94
+ """Compute the derivative of a form with respect to a coefficient in the backend language."""
95
+
96
+ def invalidate_jacobian(solver: Any):
97
+ """Invalidate the Jacobian matrix in the backend language."""
98
+
99
+ class EquationBCSplit:
100
+ ...
101
+
102
+ class EquationBC:
103
+ ...
104
+
105
+ def create_bounds_constrained_bc(V, g, sub_domain, bounds, solver_parameters=None) -> DirichletBC:
106
+ ...
107
+
108
+
109
+ def get_backend(backend: str | types.ModuleType) -> Backend:
110
+ """Get backend class from backend name.
111
+
112
+ Args:
113
+ backend: Name of the backend to get
114
+
115
+ Returns:
116
+ Backend class
117
+ """
118
+ if isinstance(backend, types.ModuleType):
119
+ return backend
120
+ if backend == "firedrake":
121
+ from .backends import firedrake as fd_backend
122
+
123
+ return fd_backend
124
+ elif backend == "dolfinx":
125
+ from .backends import dolfinx as dx_backend
126
+
127
+ return dx_backend
128
+ else:
129
+ return import_module(backend)
File without changes
@@ -0,0 +1,184 @@
1
+ """DOLFINx backend for Irksome"""
2
+
3
+ try:
4
+ from mpi4py import MPI
5
+ from petsc4py import PETSc
6
+ import basix.ufl
7
+ import dolfinx.fem.petsc
8
+ import ufl
9
+ import typing
10
+ import numpy as np
11
+
12
+ def get_stage_space(V: ufl.FunctionSpace, num_stages: int) -> ufl.FunctionSpace:
13
+ if num_stages == 1:
14
+ me = V.ufl_elemet()
15
+ else:
16
+ el = V.ufl_element()
17
+ if el.num_sub_elements > 0:
18
+ me = basix.ufl.mixed_element(
19
+ np.tile(el.sub_elements, num_stages).tolist()
20
+ )
21
+ else:
22
+ me = basix.ufl.blocked_element(el, shape=(num_stages,))
23
+ return dolfinx.fem.functionspace(V.mesh, me)
24
+
25
+ def extract_bcs(bcs: typing.Any) -> tuple[typing.Any]:
26
+ """Extract boundary conditions"""
27
+ return bcs
28
+
29
+ def create_variational_problem(F, u, bcs=None, aP=None, **kwargs):
30
+ """Create a variational problem."""
31
+ if len(F.arguments()) == 2:
32
+ a, L = ufl.system(F)
33
+ return dolfinx.fem.petsc.LinearProblem(
34
+ a,
35
+ L,
36
+ u,
37
+ bcs=bcs,
38
+ petsc_options_prefix="IrkSomeLinearSolver",
39
+ P=aP,
40
+ **kwargs,
41
+ )
42
+ else:
43
+ return dolfinx.fem.petsc.NonlinearProblem(
44
+ F,
45
+ u,
46
+ petsc_options_prefix="IrkSomeNonlinearSolver",
47
+ bcs=bcs,
48
+ petsc_options=kwargs.get("solver_parameters"),
49
+ )
50
+
51
+ def create_variational_solver(
52
+ problem: dolfinx.fem.petsc.LinearProblem | dolfinx.fem.petsc.NonlinearProblem,
53
+ **kwargs,
54
+ ):
55
+ """Create a variational solver that uses PETSc SNES or KSP."""
56
+ solver_parameters = kwargs.get("solver_parameters", {})
57
+ solver = problem.solver
58
+ solver_prefix = problem.solver.getOptionsPrefix()
59
+ opts = PETSc.Options(
60
+ )
61
+ opts.prefixPush(solver_prefix)
62
+ for k, v in solver_parameters.items():
63
+ opts.setValue(k, v)
64
+ solver.setFromOptions()
65
+ opts.prefixPop()
66
+ # For some strange reason delValue doesn't respect prefixes
67
+ for k, v in solver_parameters.items():
68
+ opts.delValue(f"{solver_prefix}{k}")
69
+ return problem
70
+
71
+ def get_function_space(u: ufl.Coefficient) -> ufl.FunctionSpace:
72
+ return u.ufl_function_space()
73
+
74
+ def get_stages(V: dolfinx.fem.FunctionSpace, num_stages: int) -> ufl.Coefficient:
75
+ """
76
+ Given a function space for a single time-step, get a duplicate of this space,
77
+ repeated `num_stages` times.
78
+
79
+ Args:
80
+ V: Space for single step
81
+ num_stages: Number of stages
82
+
83
+ Returns:
84
+ A coefficient in the new function space
85
+ """
86
+ if V.num_sub_spaces == 0:
87
+ el = basix.ufl.mixed_element([V.ufl_element()] * num_stages)
88
+ else:
89
+ el = basix.ufl.mixed_element(V.ufl_element().sub_elements * num_stages)
90
+ Vbig = dolfinx.fem.functionspace(V.mesh, el)
91
+ return dolfinx.fem.Function(Vbig)
92
+
93
+ class MeshConstant(object):
94
+ def __init__(self, msh):
95
+ self.msh = msh
96
+ try:
97
+ import basix.ufl
98
+
99
+ r_el = basix.ufl.real_element(
100
+ msh.basix_cell(), value_shape=(), dtype=dolfinx.default_scalar_type
101
+ )
102
+ self.V = dolfinx.fem.functionspace(msh, r_el)
103
+ except TypeError:
104
+ try:
105
+ import scifem
106
+ except ModuleNotFoundError:
107
+ raise RuntimeError(
108
+ "DOLFINx with real element support or Scifem is required to make mesh-constants"
109
+ )
110
+ self.V = scifem.create_real_functionspace(msh, ())
111
+
112
+ def Constant(self, val=0.0) -> ufl.Coefficient:
113
+ v = dolfinx.fem.Function(self.V)
114
+ v.value = val
115
+ return v
116
+
117
+ def get_mesh_constant(MC: MeshConstant | None) -> ufl.core.expr.Expr:
118
+ return MC.Constant if MC is not None else ufl.constantvalue.ComplexValue
119
+
120
+ class DirichletBC(dolfinx.fem.DirichletBC):
121
+ pass
122
+
123
+ def norm(
124
+ v: ufl.core.expr.Expr, norm_type: str = "L2", mesh: ufl.Mesh | None = None
125
+ ) -> float:
126
+ """Compute the norm of a function in the backend language."""
127
+ if mesh is not None:
128
+ dx = ufl.Mesure("dx", domain=mesh)
129
+ else:
130
+ dx = ufl.dx
131
+ p = 2
132
+ if norm_type.startswith("L"):
133
+ p = int(norm_type[1:])
134
+ if p < 1:
135
+ raise ValueError(f"Invalid norm type {norm_type}")
136
+ expr = ufl.inner(v, v) ** (p / 2)
137
+ form = dolfinx.fem.form(expr * dx)
138
+ else:
139
+ raise NotImplementedError(f"Norm type {norm_type} not implemented")
140
+ norm_loc = dolfinx.fem.assemble_scalar(form)
141
+ return form.mesh.comm.Allreduce(MPI.IN_PLACE, norm_loc, op=MPI.SUM) ** (1 / p)
142
+
143
+ def assemble(expr: ufl.core.expr.Expr | float):
144
+ """Assemble a UFL expression in the backend language."""
145
+ if isinstance(expr, float):
146
+ return float
147
+ else:
148
+ form = dolfinx.fem.form(expr)
149
+ if form.rank == 0:
150
+ return dolfinx.fem.assemble_scalar(form)
151
+ elif form.rank == 1:
152
+ return dolfinx.fem.assemble_vector(form)
153
+ elif form.rank == 2:
154
+ return dolfinx.fem.assemble_matrix(form)
155
+ else:
156
+ raise ValueError(f"Cannot assemble form of rank {form.rank}")
157
+
158
+ derivative = ufl.derivative
159
+ TrialFunction = ufl.TrialFunction
160
+ Function = dolfinx.fem.Function
161
+ TestFunction = ufl.TestFunction
162
+
163
+ class Constant(ufl.constantvalue.ScalarValue):
164
+ # NOTE: If dolfinx ever get's meshless constants we should change this
165
+ def assign(self, value):
166
+ self._value = value
167
+
168
+ class EquationBCSplit:
169
+ def __init__(self, *args, **kwargs):
170
+ raise NotImplementedError("DOLFINx does not support EquationBCSplit")
171
+
172
+ class EquationBC:
173
+ def __init__(self, *args, **kwargs):
174
+ raise NotImplementedError("DOLFINx does not support EquationBC")
175
+
176
+ def invalidate_jacobian(solver: dolfinx.fem.petsc.LinearProblem):
177
+ """Invalidate the Jacobian matrix in the backend language."""
178
+ raise RuntimeError("DOLFINx does not support Jacobian invalidation")
179
+
180
+ def create_bounds_constrained_bc(V, g, sub_domain, bounds, solver_parameters=None):
181
+ raise NotImplementedError("Bounds-constrained BCs are not implemented for DOLFINx")
182
+
183
+ except ModuleNotFoundError:
184
+ pass