fluxfem 0.1.3__tar.gz → 0.1.7__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.

Potentially problematic release.


This version of fluxfem might be problematic. Click here for more details.

Files changed (62) hide show
  1. fluxfem-0.1.7/PKG-INFO +222 -0
  2. fluxfem-0.1.7/README.md +202 -0
  3. {fluxfem-0.1.3 → fluxfem-0.1.7}/pyproject.toml +7 -6
  4. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/__init__.py +113 -161
  5. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/__init__.py +137 -41
  6. fluxfem-0.1.7/src/fluxfem/core/assembly.py +1352 -0
  7. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/basis.py +48 -36
  8. fluxfem-0.1.7/src/fluxfem/core/context_types.py +36 -0
  9. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/dtypes.py +3 -0
  10. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/forms.py +15 -1
  11. fluxfem-0.1.7/src/fluxfem/core/mixed_assembly.py +263 -0
  12. fluxfem-0.1.7/src/fluxfem/core/mixed_space.py +141 -0
  13. fluxfem-0.1.7/src/fluxfem/core/mixed_weakform.py +97 -0
  14. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/solver.py +2 -0
  15. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/space.py +97 -17
  16. fluxfem-0.1.7/src/fluxfem/core/weakform.py +1945 -0
  17. fluxfem-0.1.7/src/fluxfem/helpers_wf.py +97 -0
  18. fluxfem-0.1.7/src/fluxfem/mesh/__init__.py +81 -0
  19. fluxfem-0.1.7/src/fluxfem/mesh/base.py +558 -0
  20. fluxfem-0.1.7/src/fluxfem/mesh/contact.py +786 -0
  21. fluxfem-0.1.7/src/fluxfem/mesh/dtypes.py +7 -0
  22. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/mesh/hex.py +11 -10
  23. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/mesh/io.py +8 -4
  24. fluxfem-0.1.7/src/fluxfem/mesh/mortar.py +3907 -0
  25. fluxfem-0.1.7/src/fluxfem/mesh/supermesh.py +316 -0
  26. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/mesh/surface.py +22 -4
  27. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/mesh/tet.py +10 -4
  28. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/elasticity/linear.py +2 -2
  29. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/__init__.py +14 -1
  30. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/bc.py +32 -2
  31. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/dirichlet.py +81 -1
  32. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/newton.py +235 -33
  33. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/solve_runner.py +22 -0
  34. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/sparse.py +101 -7
  35. fluxfem-0.1.3/PKG-INFO +0 -125
  36. fluxfem-0.1.3/README.md +0 -105
  37. fluxfem-0.1.3/src/fluxfem/core/assembly.py +0 -788
  38. fluxfem-0.1.3/src/fluxfem/core/weakform.py +0 -828
  39. fluxfem-0.1.3/src/fluxfem/helpers_wf.py +0 -44
  40. fluxfem-0.1.3/src/fluxfem/mesh/__init__.py +0 -29
  41. fluxfem-0.1.3/src/fluxfem/mesh/base.py +0 -244
  42. {fluxfem-0.1.3 → fluxfem-0.1.7}/LICENSE +0 -0
  43. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/data.py +0 -0
  44. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/core/interp.py +0 -0
  45. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/helpers_ts.py +0 -0
  46. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/mesh/predicate.py +0 -0
  47. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/__init__.py +0 -0
  48. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/diffusion.py +0 -0
  49. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/elasticity/__init__.py +0 -0
  50. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/elasticity/hyperelastic.py +0 -0
  51. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/elasticity/materials.py +0 -0
  52. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/elasticity/stress.py +0 -0
  53. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/operators.py +0 -0
  54. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/physics/postprocess.py +0 -0
  55. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/cg.py +0 -0
  56. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/history.py +0 -0
  57. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/result.py +0 -0
  58. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/solver/solver.py +0 -0
  59. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/tools/__init__.py +0 -0
  60. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/tools/jit.py +0 -0
  61. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/tools/timer.py +0 -0
  62. {fluxfem-0.1.3 → fluxfem-0.1.7}/src/fluxfem/tools/visualizer.py +0 -0
fluxfem-0.1.7/PKG-INFO ADDED
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.1
2
+ Name: fluxfem
3
+ Version: 0.1.7
4
+ Summary: FluxFEM: A weak-form-centric differentiable finite element framework in JAX
5
+ License: Apache-2.0
6
+ Author: Kohei Watanabe
7
+ Author-email: koheitech001@gmail.com
8
+ Requires-Python: >=3.11,<3.14
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Dist: jax (>=0.8.2,<0.9.0)
14
+ Requires-Dist: jaxlib (>=0.8.2,<0.9.0)
15
+ Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
16
+ Requires-Dist: meshio (>=5.3.5,<6.0.0)
17
+ Requires-Dist: pyvista (>=0.46.4,<0.47.0)
18
+ Description-Content-Type: text/markdown
19
+
20
+ [![PyPI version](https://img.shields.io/pypi/v/fluxfem.svg?cacheSeconds=60)](https://pypi.org/project/fluxfem/)
21
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
22
+ [![Python Version](https://img.shields.io/pypi/pyversions/fluxfem.svg)](https://pypi.org/project/fluxfem/)
23
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/python-tests.yml/badge.svg)
24
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/sphinx.yml/badge.svg)
25
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18055465.svg)](https://doi.org/10.5281/zenodo.18055465)
26
+
27
+
28
+ # FluxFEM
29
+ A weak-form-centric differentiable finite element framework in JAX,
30
+ where variational forms are treated as first-class, differentiable programs.
31
+
32
+ ## Examples and Features
33
+ <table>
34
+ <tr>
35
+ <td align="center"><b>Example 1: Diffusion</b></td>
36
+ <td align="center"><b>Example 2: Neo Neohookean Hyper Elasticity</b></td>
37
+ </tr>
38
+ <tr>
39
+ <td align="center">
40
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/diffusion_mms_timeseries.gif" alt="Diffusion-mms" width="400">
41
+ </td>
42
+ <td align="center">
43
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/Neo-Hookean-deformedx20000.png" alt="Neo-Hookean" width="400">
44
+ </td>
45
+ </tr>
46
+ </table>
47
+
48
+
49
+ ## Features
50
+ - Built on JAX, enabling automatic differentiation with grad, jit, vmap, and related transformations.
51
+ - Weak-form–centric API that keeps formulations close to code; weak forms are represented as expression trees and compiled into element kernels, enabling automatic differentiation of residuals, tangents, and objectives.
52
+ - Two assembly approaches: tensor-based (scikit-fem–style) assembly and weak-form-based assembly.
53
+ - Handles both linear and nonlinear analyses with AD in JAX.
54
+
55
+ ## Usage
56
+
57
+ This library provides two assembly approaches.
58
+
59
+ - A tensor-based assembly, where trial and test functions are represented explicitly as element-level tensors and assembled accordingly (in the style of scikit-fem).
60
+ - A weak-form-based assembly, where the variational form is written symbolically and compiled before assembly.
61
+
62
+ The two approaches are functionally equivalent and share the same element-level execution model,
63
+ but they differ in how you author the weak form. The example below mirrors the paper's diffusion
64
+ case and makes the distinction explicit with `jnp`.
65
+
66
+
67
+ ## Assembly Flow
68
+ All expressions are first compiled into an element-level evaluation plan,
69
+ which operates on quadrature-point–major tensors.
70
+ This plan is then executed independently for each element during assembly.
71
+
72
+ As a result, both assembly approaches:
73
+ - use the same quadrature-major (q, a, i) data layout,
74
+ - perform element-local tensor contractions,
75
+ - and are fully compatible with JAX transformations such as `jit`, `vmap`, and automatic differentiation.
76
+
77
+ ### kernel-based assembly (explicit JIT units)
78
+ If you want to control JIT boundaries explicitly, build a JIT-compiled element kernel
79
+ and pass it to `space.assemble_*`. The kernel must return the integrated element
80
+ contribution (not the quadrature integrand).
81
+
82
+ ```Python
83
+ import fluxfem as ff
84
+ import jax
85
+ import jax.numpy as jnp
86
+
87
+ space = ff.make_hex_space(mesh, dim=1, intorder=2)
88
+
89
+ # bilinear: kernel(ctx) -> (n_ldofs, n_ldofs)
90
+ ker_K = ff.make_element_bilinear_kernel(ff.diffusion_form, 1.0, jit=True)
91
+ K = space.assemble_bilinear_form(ff.diffusion_form, 1.0, kernel=ker_K)
92
+
93
+ # linear: kernel(ctx) -> (n_ldofs,)
94
+ def linear_kernel(ctx):
95
+ integrand = ff.scalar_body_force_form(ctx, 2.0)
96
+ wJ = ctx.w * ctx.test.detJ
97
+ return (integrand * wJ[:, None]).sum(axis=0)
98
+
99
+ ker_F = jax.jit(linear_kernel)
100
+ F = space.assemble_linear_form(ff.scalar_body_force_form, 2.0, kernel=ker_F)
101
+ ```
102
+
103
+ ### tensor-based vs weak-form-based (diffusion example)
104
+
105
+ #### tensor-based assembly
106
+ The tensor-based assembly provides an explicit, low-level formulation with element kernels written using jax.numpy.(`jnp`).
107
+ ```Python
108
+ import fluxfem as ff
109
+ import jax.numpy as jnp
110
+
111
+ def diffusion_form(ctx: ff.FormContext, kappa):
112
+ # ctx.test.gradN / ctx.trial.gradN: (n_qp, n_nodes, dim)
113
+ # output tensor: (n_qp, n_nodes, n_nodes)
114
+ return kappa * jnp.einsum("qia,qja->qij", ctx.test.gradN, ctx.trial.gradN)
115
+
116
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
117
+ params = ff.Params(kappa=1.0)
118
+ K_ts = space.assemble_bilinear_form(diffusion_form, params=params.kappa)
119
+ ```
120
+
121
+ #### weak-form-based assembly
122
+ In the weak-form-based assembly, the variational formulation itself is the primary object.
123
+ The expression below defines a symbolic computation graph, which is later compiled and executed at the element level.
124
+
125
+ ```Python
126
+ import fluxfem as ff
127
+ import fluxfem.helpers_wf as h_wf
128
+
129
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
130
+ params = ff.Params(kappa=1.0)
131
+
132
+ # u, v are symbolic trial/test fields (weak-form DSL objects).
133
+ # u.grad / v.grad are symbolic nodes (expression tree), not numeric arrays.
134
+ # dOmega() is the integral measure; the whole expression is compiled before assembly.
135
+ form_wf = ff.BilinearForm.volume(
136
+ lambda u, v, p: p.kappa * (v.grad @ u.grad) * h_wf.dOmega()
137
+ ).get_compiled()
138
+
139
+ K_wf = space.assemble_bilinear_form(form_wf, params=params)
140
+ ```
141
+
142
+ ### Linear Elasticity assembly (weak-form based assembly)
143
+
144
+ ```Python
145
+ import fluxfem as ff
146
+ import fluxfem.helpers_wf as h_wf
147
+
148
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
149
+ D = ff.isotropic_3d_D(1.0, 0.3)
150
+
151
+ form_wf = ff.BilinearForm.volume(
152
+ lambda u, v, D: h_wf.ddot(v.sym_grad, D @ u.sym_grad) * h_wf.dOmega()
153
+ ).get_compiled()
154
+
155
+ K = space.assemble_bilinear_form(form_wf, params=D)
156
+ ```
157
+
158
+ ### Neo-Hookean residual assembly (weak-form DSL)
159
+ Below is a Neo-Hookean hyperelasticity example written in weak form.
160
+ The residual is expressed symbolically and compiled into element-level kernels executed per element.
161
+ No manual derivation of tangent operators is required; consistent tangents (Jacobians) for Newton-type solvers are obtained automatically via JAX AD.
162
+
163
+ ```Python
164
+ def neo_hookean_residual_wf(v, u, params):
165
+ mu = params["mu"]
166
+ lam = params["lam"]
167
+ F = h_wf.I(3) + h_wf.grad(u) # deformation gradient
168
+ C = h_wf.matmul(h_wf.transpose(F), F)
169
+ C_inv = h_wf.inv(C)
170
+ J = h_wf.det(F)
171
+
172
+ S = mu * (h_wf.I(3) - C_inv) + lam * h_wf.log(J) * C_inv
173
+ dE = 0.5 * (h_wf.matmul(h_wf.grad(v), F) + h_wf.transpose(h_wf.matmul(h_wf.grad(v), F)))
174
+ return h_wf.ddot(S, dE) * h_wf.dOmega()
175
+ ```
176
+
177
+
178
+ ### autodiff + jit compile
179
+
180
+ You can differentiate through the solve and JIT compile the hot path.
181
+ The inverse diffusion tutorial shows this pattern:
182
+
183
+ ```Python
184
+ def loss_theta(theta):
185
+ kappa = jnp.exp(theta)
186
+ u = solve_u_jit(kappa, traction_true)
187
+ diff = u[obs_idx_j] - u_obs[obs_idx_j]
188
+ return 0.5 * jnp.mean(diff * diff)
189
+
190
+ solve_u_jit = jax.jit(solve_u)
191
+ loss_theta_jit = jax.jit(loss_theta)
192
+ grad_fn = jax.jit(jax.grad(loss_theta))
193
+ ```
194
+
195
+ ## Documentation
196
+
197
+ Full documentation, tutorials, and API reference are hosted at [this site](https://fluxfem.readthedocs.io/en/latest/).
198
+
199
+ ## SetUp
200
+
201
+ You can install **FluxFEM** either via **pip** or **Poetry**.
202
+
203
+ #### Supported Python Versions
204
+
205
+ FluxFEM supports **Python 3.11–3.13**:
206
+
207
+
208
+ **Choose one of the following methods:**
209
+
210
+ ### Using pip
211
+ ```bash
212
+ pip install fluxfem
213
+ ```
214
+
215
+ ### Using poetry
216
+ ```bash
217
+ poetry add fluxfem
218
+ ```
219
+
220
+ ## Acknowledgements
221
+ I acknowledge the open-source software, libraries, and communities that made this work possible.
222
+
@@ -0,0 +1,202 @@
1
+ [![PyPI version](https://img.shields.io/pypi/v/fluxfem.svg?cacheSeconds=60)](https://pypi.org/project/fluxfem/)
2
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
3
+ [![Python Version](https://img.shields.io/pypi/pyversions/fluxfem.svg)](https://pypi.org/project/fluxfem/)
4
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/python-tests.yml/badge.svg)
5
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/sphinx.yml/badge.svg)
6
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18055465.svg)](https://doi.org/10.5281/zenodo.18055465)
7
+
8
+
9
+ # FluxFEM
10
+ A weak-form-centric differentiable finite element framework in JAX,
11
+ where variational forms are treated as first-class, differentiable programs.
12
+
13
+ ## Examples and Features
14
+ <table>
15
+ <tr>
16
+ <td align="center"><b>Example 1: Diffusion</b></td>
17
+ <td align="center"><b>Example 2: Neo Neohookean Hyper Elasticity</b></td>
18
+ </tr>
19
+ <tr>
20
+ <td align="center">
21
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/diffusion_mms_timeseries.gif" alt="Diffusion-mms" width="400">
22
+ </td>
23
+ <td align="center">
24
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/Neo-Hookean-deformedx20000.png" alt="Neo-Hookean" width="400">
25
+ </td>
26
+ </tr>
27
+ </table>
28
+
29
+
30
+ ## Features
31
+ - Built on JAX, enabling automatic differentiation with grad, jit, vmap, and related transformations.
32
+ - Weak-form–centric API that keeps formulations close to code; weak forms are represented as expression trees and compiled into element kernels, enabling automatic differentiation of residuals, tangents, and objectives.
33
+ - Two assembly approaches: tensor-based (scikit-fem–style) assembly and weak-form-based assembly.
34
+ - Handles both linear and nonlinear analyses with AD in JAX.
35
+
36
+ ## Usage
37
+
38
+ This library provides two assembly approaches.
39
+
40
+ - A tensor-based assembly, where trial and test functions are represented explicitly as element-level tensors and assembled accordingly (in the style of scikit-fem).
41
+ - A weak-form-based assembly, where the variational form is written symbolically and compiled before assembly.
42
+
43
+ The two approaches are functionally equivalent and share the same element-level execution model,
44
+ but they differ in how you author the weak form. The example below mirrors the paper's diffusion
45
+ case and makes the distinction explicit with `jnp`.
46
+
47
+
48
+ ## Assembly Flow
49
+ All expressions are first compiled into an element-level evaluation plan,
50
+ which operates on quadrature-point–major tensors.
51
+ This plan is then executed independently for each element during assembly.
52
+
53
+ As a result, both assembly approaches:
54
+ - use the same quadrature-major (q, a, i) data layout,
55
+ - perform element-local tensor contractions,
56
+ - and are fully compatible with JAX transformations such as `jit`, `vmap`, and automatic differentiation.
57
+
58
+ ### kernel-based assembly (explicit JIT units)
59
+ If you want to control JIT boundaries explicitly, build a JIT-compiled element kernel
60
+ and pass it to `space.assemble_*`. The kernel must return the integrated element
61
+ contribution (not the quadrature integrand).
62
+
63
+ ```Python
64
+ import fluxfem as ff
65
+ import jax
66
+ import jax.numpy as jnp
67
+
68
+ space = ff.make_hex_space(mesh, dim=1, intorder=2)
69
+
70
+ # bilinear: kernel(ctx) -> (n_ldofs, n_ldofs)
71
+ ker_K = ff.make_element_bilinear_kernel(ff.diffusion_form, 1.0, jit=True)
72
+ K = space.assemble_bilinear_form(ff.diffusion_form, 1.0, kernel=ker_K)
73
+
74
+ # linear: kernel(ctx) -> (n_ldofs,)
75
+ def linear_kernel(ctx):
76
+ integrand = ff.scalar_body_force_form(ctx, 2.0)
77
+ wJ = ctx.w * ctx.test.detJ
78
+ return (integrand * wJ[:, None]).sum(axis=0)
79
+
80
+ ker_F = jax.jit(linear_kernel)
81
+ F = space.assemble_linear_form(ff.scalar_body_force_form, 2.0, kernel=ker_F)
82
+ ```
83
+
84
+ ### tensor-based vs weak-form-based (diffusion example)
85
+
86
+ #### tensor-based assembly
87
+ The tensor-based assembly provides an explicit, low-level formulation with element kernels written using jax.numpy.(`jnp`).
88
+ ```Python
89
+ import fluxfem as ff
90
+ import jax.numpy as jnp
91
+
92
+ def diffusion_form(ctx: ff.FormContext, kappa):
93
+ # ctx.test.gradN / ctx.trial.gradN: (n_qp, n_nodes, dim)
94
+ # output tensor: (n_qp, n_nodes, n_nodes)
95
+ return kappa * jnp.einsum("qia,qja->qij", ctx.test.gradN, ctx.trial.gradN)
96
+
97
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
98
+ params = ff.Params(kappa=1.0)
99
+ K_ts = space.assemble_bilinear_form(diffusion_form, params=params.kappa)
100
+ ```
101
+
102
+ #### weak-form-based assembly
103
+ In the weak-form-based assembly, the variational formulation itself is the primary object.
104
+ The expression below defines a symbolic computation graph, which is later compiled and executed at the element level.
105
+
106
+ ```Python
107
+ import fluxfem as ff
108
+ import fluxfem.helpers_wf as h_wf
109
+
110
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
111
+ params = ff.Params(kappa=1.0)
112
+
113
+ # u, v are symbolic trial/test fields (weak-form DSL objects).
114
+ # u.grad / v.grad are symbolic nodes (expression tree), not numeric arrays.
115
+ # dOmega() is the integral measure; the whole expression is compiled before assembly.
116
+ form_wf = ff.BilinearForm.volume(
117
+ lambda u, v, p: p.kappa * (v.grad @ u.grad) * h_wf.dOmega()
118
+ ).get_compiled()
119
+
120
+ K_wf = space.assemble_bilinear_form(form_wf, params=params)
121
+ ```
122
+
123
+ ### Linear Elasticity assembly (weak-form based assembly)
124
+
125
+ ```Python
126
+ import fluxfem as ff
127
+ import fluxfem.helpers_wf as h_wf
128
+
129
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
130
+ D = ff.isotropic_3d_D(1.0, 0.3)
131
+
132
+ form_wf = ff.BilinearForm.volume(
133
+ lambda u, v, D: h_wf.ddot(v.sym_grad, D @ u.sym_grad) * h_wf.dOmega()
134
+ ).get_compiled()
135
+
136
+ K = space.assemble_bilinear_form(form_wf, params=D)
137
+ ```
138
+
139
+ ### Neo-Hookean residual assembly (weak-form DSL)
140
+ Below is a Neo-Hookean hyperelasticity example written in weak form.
141
+ The residual is expressed symbolically and compiled into element-level kernels executed per element.
142
+ No manual derivation of tangent operators is required; consistent tangents (Jacobians) for Newton-type solvers are obtained automatically via JAX AD.
143
+
144
+ ```Python
145
+ def neo_hookean_residual_wf(v, u, params):
146
+ mu = params["mu"]
147
+ lam = params["lam"]
148
+ F = h_wf.I(3) + h_wf.grad(u) # deformation gradient
149
+ C = h_wf.matmul(h_wf.transpose(F), F)
150
+ C_inv = h_wf.inv(C)
151
+ J = h_wf.det(F)
152
+
153
+ S = mu * (h_wf.I(3) - C_inv) + lam * h_wf.log(J) * C_inv
154
+ dE = 0.5 * (h_wf.matmul(h_wf.grad(v), F) + h_wf.transpose(h_wf.matmul(h_wf.grad(v), F)))
155
+ return h_wf.ddot(S, dE) * h_wf.dOmega()
156
+ ```
157
+
158
+
159
+ ### autodiff + jit compile
160
+
161
+ You can differentiate through the solve and JIT compile the hot path.
162
+ The inverse diffusion tutorial shows this pattern:
163
+
164
+ ```Python
165
+ def loss_theta(theta):
166
+ kappa = jnp.exp(theta)
167
+ u = solve_u_jit(kappa, traction_true)
168
+ diff = u[obs_idx_j] - u_obs[obs_idx_j]
169
+ return 0.5 * jnp.mean(diff * diff)
170
+
171
+ solve_u_jit = jax.jit(solve_u)
172
+ loss_theta_jit = jax.jit(loss_theta)
173
+ grad_fn = jax.jit(jax.grad(loss_theta))
174
+ ```
175
+
176
+ ## Documentation
177
+
178
+ Full documentation, tutorials, and API reference are hosted at [this site](https://fluxfem.readthedocs.io/en/latest/).
179
+
180
+ ## SetUp
181
+
182
+ You can install **FluxFEM** either via **pip** or **Poetry**.
183
+
184
+ #### Supported Python Versions
185
+
186
+ FluxFEM supports **Python 3.11–3.13**:
187
+
188
+
189
+ **Choose one of the following methods:**
190
+
191
+ ### Using pip
192
+ ```bash
193
+ pip install fluxfem
194
+ ```
195
+
196
+ ### Using poetry
197
+ ```bash
198
+ poetry add fluxfem
199
+ ```
200
+
201
+ ## Acknowledgements
202
+ I acknowledge the open-source software, libraries, and communities that made this work possible.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fluxfem"
3
- version = "0.1.3"
3
+ version = "0.1.7"
4
4
  description = ""
5
5
  authors = [
6
6
  {name = "Kohei Watanabe",email = "koheitech001@gmail.com"}
@@ -18,13 +18,13 @@ dependencies = [
18
18
  "meshio (>=5.3.5,<6.0.0)",
19
19
  "matplotlib (>=3.10.7,<4.0.0)",
20
20
  # Note: jax versioning currently around 0.8.x. Allow up to next minor.
21
- "jax (==0.8.2)",
22
- "jaxlib (==0.8.2)"
21
+ "jax (>=0.8.2,<0.9.0)",
22
+ "jaxlib (>=0.8.2,<0.9.0)",
23
23
  ]
24
24
 
25
25
  [tool.poetry]
26
26
  name = "fluxfem"
27
- version = "0.1.3"
27
+ version = "0.1.7"
28
28
  description = "FluxFEM: A weak-form-centric differentiable finite element framework in JAX"
29
29
  authors = ["Kohei Watanabe <koheitech001@gmail.com>"]
30
30
  readme = "README.md"
@@ -39,8 +39,8 @@ python = ">=3.11,<3.14"
39
39
  pyvista = ">=0.46.4,<0.47.0"
40
40
  meshio = ">=5.3.5,<6.0.0"
41
41
  matplotlib = ">=3.10.7,<4.0.0"
42
- jax = "==0.8.2"
43
- jaxlib = "==0.8.2"
42
+ jax = ">=0.8.2,<0.9.0"
43
+ jaxlib = ">=0.8.2,<0.9.0"
44
44
 
45
45
 
46
46
  [tool.poetry.group.dev]
@@ -59,6 +59,7 @@ sphinx-rtd-theme = { version = "^3.0.2", python = ">=3.11" }
59
59
  myst-parser = { version = "^4.0.1", python = ">=3.11" }
60
60
  sphinx-autodoc-typehints = { version = "^3.2.0", python = ">=3.11" }
61
61
  sphinx-sitemap = { version = "^2.6.0", python = ">=3.11" }
62
+ shapely = "^2.1.2"
62
63
 
63
64
  [build-system]
64
65
  requires = ["poetry-core>=2.0.0,<3.0.0"]