fluxfem 0.1.4__py3-none-any.whl → 0.2.1__py3-none-any.whl

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 (53) hide show
  1. fluxfem/__init__.py +69 -13
  2. fluxfem/core/__init__.py +140 -53
  3. fluxfem/core/assembly.py +691 -97
  4. fluxfem/core/basis.py +75 -54
  5. fluxfem/core/context_types.py +36 -12
  6. fluxfem/core/dtypes.py +9 -1
  7. fluxfem/core/forms.py +10 -0
  8. fluxfem/core/mixed_assembly.py +263 -0
  9. fluxfem/core/mixed_space.py +382 -0
  10. fluxfem/core/mixed_weakform.py +97 -0
  11. fluxfem/core/solver.py +2 -0
  12. fluxfem/core/space.py +315 -30
  13. fluxfem/core/weakform.py +821 -42
  14. fluxfem/helpers_wf.py +49 -0
  15. fluxfem/mesh/__init__.py +54 -2
  16. fluxfem/mesh/base.py +318 -9
  17. fluxfem/mesh/contact.py +841 -0
  18. fluxfem/mesh/dtypes.py +12 -0
  19. fluxfem/mesh/hex.py +17 -16
  20. fluxfem/mesh/io.py +9 -6
  21. fluxfem/mesh/mortar.py +3970 -0
  22. fluxfem/mesh/supermesh.py +318 -0
  23. fluxfem/mesh/surface.py +104 -26
  24. fluxfem/mesh/tet.py +16 -7
  25. fluxfem/physics/diffusion.py +3 -0
  26. fluxfem/physics/elasticity/hyperelastic.py +35 -3
  27. fluxfem/physics/elasticity/linear.py +22 -4
  28. fluxfem/physics/elasticity/stress.py +9 -5
  29. fluxfem/physics/operators.py +12 -5
  30. fluxfem/physics/postprocess.py +29 -3
  31. fluxfem/solver/__init__.py +47 -2
  32. fluxfem/solver/bc.py +38 -2
  33. fluxfem/solver/block_matrix.py +284 -0
  34. fluxfem/solver/block_system.py +477 -0
  35. fluxfem/solver/cg.py +150 -55
  36. fluxfem/solver/dirichlet.py +358 -5
  37. fluxfem/solver/history.py +15 -3
  38. fluxfem/solver/newton.py +260 -70
  39. fluxfem/solver/petsc.py +445 -0
  40. fluxfem/solver/preconditioner.py +109 -0
  41. fluxfem/solver/result.py +18 -0
  42. fluxfem/solver/solve_runner.py +208 -23
  43. fluxfem/solver/solver.py +35 -12
  44. fluxfem/solver/sparse.py +149 -15
  45. fluxfem/tools/jit.py +19 -7
  46. fluxfem/tools/timer.py +14 -12
  47. fluxfem/tools/visualizer.py +16 -4
  48. fluxfem-0.2.1.dist-info/METADATA +314 -0
  49. fluxfem-0.2.1.dist-info/RECORD +59 -0
  50. fluxfem-0.1.4.dist-info/METADATA +0 -127
  51. fluxfem-0.1.4.dist-info/RECORD +0 -48
  52. {fluxfem-0.1.4.dist-info → fluxfem-0.2.1.dist-info}/LICENSE +0 -0
  53. {fluxfem-0.1.4.dist-info → fluxfem-0.2.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,314 @@
1
+ Metadata-Version: 2.1
2
+ Name: fluxfem
3
+ Version: 0.2.1
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.12,<3.14
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Provides-Extra: cpu
13
+ Provides-Extra: cuda12
14
+ Provides-Extra: petsc
15
+ Requires-Dist: jax (>=0.8.2,<0.9.0) ; extra == "cpu" or extra == "cuda12"
16
+ Requires-Dist: jax-cuda12-pjrt (==0.8.2) ; extra == "cuda12"
17
+ Requires-Dist: jax-cuda12-plugin (==0.8.2) ; extra == "cuda12"
18
+ Requires-Dist: jaxlib (>=0.8.2,<0.9.0) ; extra == "cpu" or extra == "cuda12"
19
+ Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
20
+ Requires-Dist: meshio (>=5.3.5,<6.0.0)
21
+ Requires-Dist: petsc4py (==3.23.6) ; extra == "petsc"
22
+ Requires-Dist: pyproject (>=1!0.1.2,<1!0.2.0)
23
+ Requires-Dist: pyproject-toml (>=0.1.0,<0.2.0)
24
+ Requires-Dist: pyvista (>=0.46.4,<0.47.0)
25
+ Description-Content-Type: text/markdown
26
+
27
+ [![PyPI version](https://img.shields.io/pypi/v/fluxfem.svg?cacheSeconds=60)](https://pypi.org/project/fluxfem/)
28
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
29
+ [![Python Version](https://img.shields.io/pypi/pyversions/fluxfem.svg)](https://pypi.org/project/fluxfem/)
30
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/python-tests.yml/badge.svg)
31
+ ![CI](https://github.com/kevin-tofu/fluxfem/actions/workflows/sphinx.yml/badge.svg)
32
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.18055465.svg)](https://doi.org/10.5281/zenodo.18055465)
33
+
34
+
35
+ # FluxFEM
36
+ A weak-form-centric differentiable finite element framework in JAX,
37
+ where variational forms are treated as first-class, differentiable programs.
38
+
39
+ ## Examples and Features
40
+ <table>
41
+ <tr>
42
+ <td align="center"><b>Example 1: Diffusion</b></td>
43
+ <td align="center"><b>Example 2: Neo Neohookean Hyper Elasticity</b></td>
44
+ </tr>
45
+ <tr>
46
+ <td align="center">
47
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/diffusion_mms_timeseries.gif" alt="Diffusion-mms" width="400">
48
+ </td>
49
+ <td align="center">
50
+ <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/Neo-Hookean-deformedx20000.png" alt="Neo-Hookean" width="400">
51
+ </td>
52
+ </tr>
53
+ </table>
54
+
55
+
56
+ ## Features
57
+ - Built on JAX, enabling automatic differentiation with grad, jit, vmap, and related transformations.
58
+ - 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.
59
+ - Two assembly approaches: tensor-based (scikit-fem–style) assembly and weak-form-based assembly.
60
+ - Handles both linear and nonlinear analyses with AD in JAX.
61
+ - Optional PETSc/PETSc-shell solvers via `petsc4py` for scalable linear solves (add `fluxfem[petsc]`).
62
+
63
+ ## Usage
64
+
65
+ This library provides two assembly approaches.
66
+
67
+ - 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).
68
+ - A weak-form-based assembly, where the variational form is written symbolically and compiled before assembly.
69
+
70
+ The two approaches are functionally equivalent and share the same element-level execution model,
71
+ but they differ in how you author the weak form. The example below mirrors the paper's diffusion
72
+ case and makes the distinction explicit with `jnp`.
73
+
74
+
75
+ ## Assembly Flow
76
+ All expressions are first compiled into an element-level evaluation plan,
77
+ which operates on quadrature-point–major tensors.
78
+ This plan is then executed independently for each element during assembly.
79
+
80
+ As a result, both assembly approaches:
81
+ - use the same quadrature-major (q, a, i) data layout,
82
+ - perform element-local tensor contractions,
83
+ - and are fully compatible with JAX transformations such as `jit`, `vmap`, and automatic differentiation.
84
+
85
+ ### kernel-based assembly (explicit JIT units)
86
+ If you want to control JIT boundaries explicitly, build a JIT-compiled element kernel
87
+ and pass it to `space.assemble`. The kernel must return the integrated element
88
+ contribution (not the quadrature integrand). For untagged raw kernels, pass `kind=`.
89
+
90
+ ```Python
91
+ import fluxfem as ff
92
+ import jax
93
+ import jax.numpy as jnp
94
+
95
+ space = ff.make_hex_space(mesh, dim=1, intorder=2)
96
+
97
+ # bilinear: kernel(ctx) -> (n_ldofs, n_ldofs)
98
+ ker_K = ff.make_element_bilinear_kernel(ff.diffusion_form, 1.0, jit=True)
99
+ K = space.assemble(ff.diffusion_form, 1.0, kernel=ker_K)
100
+
101
+ # linear: kernel(ctx) -> (n_ldofs,)
102
+ def linear_kernel(ctx):
103
+ integrand = ff.scalar_body_force_form(ctx, 2.0)
104
+ wJ = ctx.w * ctx.test.detJ
105
+ return (integrand * wJ[:, None]).sum(axis=0)
106
+
107
+ ker_F = jax.jit(linear_kernel)
108
+ F = space.assemble(ff.scalar_body_force_form, 2.0, kernel=ker_F)
109
+ ```
110
+
111
+ ### tensor-based vs weak-form-based (diffusion example)
112
+
113
+ #### tensor-based assembly
114
+ The tensor-based assembly provides an explicit, low-level formulation with element kernels written using jax.numpy.(`jnp`).
115
+ ```Python
116
+ import fluxfem as ff
117
+ import jax.numpy as jnp
118
+
119
+ @ff.kernel(kind="bilinear", domain="volume")
120
+ def diffusion_form(ctx: ff.FormContext, kappa):
121
+ # ctx.test.gradN / ctx.trial.gradN: (n_qp, n_nodes, dim)
122
+ # output tensor: (n_qp, n_nodes, n_nodes)
123
+ return kappa * jnp.einsum("qia,qja->qij", ctx.test.gradN, ctx.trial.gradN)
124
+
125
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
126
+ params = ff.Params(kappa=1.0)
127
+ K_ts = space.assemble(diffusion_form, params=params.kappa)
128
+ ```
129
+
130
+ #### weak-form-based assembly
131
+ In the weak-form-based assembly, the variational formulation itself is the primary object.
132
+ The expression below defines a symbolic computation graph, which is later compiled and executed at the element level.
133
+
134
+ ```Python
135
+ import fluxfem as ff
136
+ import fluxfem.helpers_wf as h_wf
137
+
138
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
139
+ params = ff.Params(kappa=1.0)
140
+
141
+ # u, v are symbolic trial/test fields (weak-form DSL objects).
142
+ # u.grad / v.grad are symbolic nodes (expression tree), not numeric arrays.
143
+ # dOmega() is the integral measure; the whole expression is compiled before assembly.
144
+ form_wf = ff.BilinearForm.volume(
145
+ lambda u, v, p: p.kappa * (v.grad @ u.grad) * h_wf.dOmega()
146
+ ).get_compiled()
147
+
148
+ K_wf = space.assemble(form_wf, params=params)
149
+ ```
150
+
151
+ ### Linear Elasticity assembly (weak-form based assembly)
152
+
153
+ ```Python
154
+ import fluxfem as ff
155
+ import fluxfem.helpers_wf as h_wf
156
+
157
+ space = ff.make_hex_space(mesh, dim=3, intorder=2)
158
+ D = ff.isotropic_3d_D(1.0, 0.3)
159
+
160
+ form_wf = ff.BilinearForm.volume(
161
+ lambda u, v, D: h_wf.ddot(v.sym_grad, D @ u.sym_grad) * h_wf.dOmega()
162
+ ).get_compiled()
163
+
164
+ K = space.assemble(form_wf, params=D)
165
+ ```
166
+
167
+ ### Neo-Hookean residual assembly (weak-form DSL)
168
+ Below is a Neo-Hookean hyperelasticity example written in weak form.
169
+ The residual is expressed symbolically and compiled into element-level kernels executed per element.
170
+ No manual derivation of tangent operators is required; consistent tangents (Jacobians) for Newton-type solvers are obtained automatically via JAX AD.
171
+
172
+ ```Python
173
+ def neo_hookean_residual_wf(v, u, params):
174
+ mu = params["mu"]
175
+ lam = params["lam"]
176
+ F = h_wf.I(3) + h_wf.grad(u) # deformation gradient
177
+ C = h_wf.matmul(h_wf.transpose(F), F)
178
+ C_inv = h_wf.inv(C)
179
+ J = h_wf.det(F)
180
+
181
+ S = mu * (h_wf.I(3) - C_inv) + lam * h_wf.log(J) * C_inv
182
+ dE = 0.5 * (h_wf.matmul(h_wf.grad(v), F) + h_wf.transpose(h_wf.matmul(h_wf.grad(v), F)))
183
+ return h_wf.ddot(S, dE) * h_wf.dOmega()
184
+
185
+ res_form = ff.ResidualForm.volume(neo_hookean_residual_wf).get_compiled()
186
+ ```
187
+
188
+
189
+ ### autodiff + jit compile
190
+
191
+ You can differentiate through the solve and JIT compile the hot path.
192
+ The inverse diffusion tutorial shows this pattern:
193
+
194
+ ```Python
195
+ def loss_theta(theta):
196
+ kappa = jnp.exp(theta)
197
+ u = solve_u_jit(kappa, traction_true)
198
+ diff = u[obs_idx_j] - u_obs[obs_idx_j]
199
+ return 0.5 * jnp.mean(diff * diff)
200
+
201
+ solve_u_jit = jax.jit(solve_u)
202
+ loss_theta_jit = jax.jit(loss_theta)
203
+ grad_fn = jax.jit(jax.grad(loss_theta))
204
+ ```
205
+
206
+ ### FESpace vs FESpacePytree
207
+
208
+ Use `FESpace` for standard workflows with a fixed mesh. When you need to carry
209
+ the space through JAX transformations (e.g., shape optimization where mesh
210
+ coordinates are part of the computation), use `FESpacePytree` via
211
+ `make_*_space_pytree(...)`. This keeps the mesh/basis in the pytree so
212
+ `jax.jit`/`jax.grad` can see geometry changes.
213
+
214
+ ### Mixed systems
215
+
216
+ Mixed problems can be assembled from residual blocks and solved as a coupled system.
217
+
218
+ ```Python
219
+ import fluxfem as ff
220
+ import jax.numpy as jnp
221
+
222
+ mixed = ff.MixedFESpace({"u": space_u, "p": space_p})
223
+ residuals = ff.make_mixed_residuals(
224
+ u=res_u, # (v, u, params) -> Expr
225
+ p=res_p, # (q, u, params) -> Expr
226
+ )
227
+ problem = ff.MixedProblem(mixed, residuals, params=ff.Params(alpha=1.0))
228
+
229
+ u0 = jnp.zeros(mixed.n_dofs)
230
+ R = problem.assemble_residual(u0)
231
+ J = problem.assemble_jacobian(u0, return_flux_matrix=True)
232
+ ```
233
+
234
+ ### Block assembly
235
+
236
+ For constraints like contact problems (e.g., adding Lagrange multipliers), build
237
+ a block matrix explicitly:
238
+
239
+ ```Python
240
+ from fluxfem import solver as ff_solver
241
+
242
+ # Example blocks from contact coupling
243
+ K_uu = ...
244
+ K_cc = ...
245
+ K_uc = ...
246
+
247
+ blocks = ff_solver.make_block_matrix(
248
+ diag=ff_solver.block_diag(u=K_uu, c=K_cc),
249
+ rel={("u", "c"): K_uc},
250
+ sizes={"u": K_uu.shape[0], "c": K_cc.shape[0]},
251
+ symmetric=True,
252
+ transpose_rule="T",
253
+ )
254
+
255
+ # Lazy container; assemble when you need the global matrix.
256
+ K = blocks.assemble()
257
+ ```
258
+
259
+ FluxFEM also provides contact utilities like `ContactSurfaceSpace` to build constraint contributions.
260
+
261
+
262
+ ## Documentation
263
+
264
+ Full documentation, tutorials, and API reference are hosted at [this site](https://fluxfem.readthedocs.io/en/latest/).
265
+
266
+ ## Tutorials
267
+
268
+ - `tutorials/linearelastic_tensile_bar.py` (linear elasticity, weak-form assembly)
269
+ - `tutorials/neo_hookean_cantilever.py` (nonlinear hyperelasticity)
270
+ - `tutorials/thermoelastic_bar_1d.py` / `tutorials/thermoelastic_bar_1d_mixed.py` (thermoelastic coupling)
271
+ - `tutorials/petsc_shell_poisson_demo.py` (PETSc shell solver integration; see also `tutorials/petsc_shell_poisson_pmat_demo.py`)
272
+
273
+ ## Setup
274
+
275
+ You can install **FluxFEM** either via **pip** or **Poetry**.
276
+
277
+ #### Supported Python Versions
278
+
279
+ FluxFEM supports **Python 3.11–3.13**:
280
+
281
+
282
+ **Choose one of the following methods:**
283
+
284
+ ### Using pip
285
+ ```bash
286
+ pip install fluxfem
287
+ pip install "fluxfem[cuda12]" -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.html
288
+ ```
289
+
290
+ ### Using poetry
291
+ ```bash
292
+ poetry add fluxfem
293
+ poetry add fluxfem[cuda12]
294
+ ```
295
+
296
+ ## PETSc Integration
297
+
298
+ Optional PETSc-based solvers are available via `petsc4py`. Enable with the extra:
299
+
300
+ ```bash
301
+ poetry add fluxfem --extras "petsc"
302
+ ```
303
+
304
+ Note: newer `petsc4py` expects PETSc builds that include the `PetscRegressor`
305
+ API. If your PETSc build does not have it, `petsc4py` will fail to compile. In
306
+ that case, rebuild PETSc with regressor support or pin `petsc4py` to a version
307
+ compatible with your PETSc build.
308
+
309
+ GPU note: this repo currently tests CUDA via the `cuda12` extra only. Other CUDA
310
+ versions are not covered by CI and may require manual JAX installation.
311
+
312
+ ## Acknowledgements
313
+ I acknowledge the open-source software, libraries, and communities that made this work possible.
314
+
@@ -0,0 +1,59 @@
1
+ fluxfem/__init__.py,sha256=hHJEJ4P89uDvziScw-hzs82MIt-K5OBGFgF5ojoI9B4,7846
2
+ fluxfem/core/__init__.py,sha256=av60HQ0K8oaLko0vKc_GNsNs35TayR8BPGp463GKFN4,10898
3
+ fluxfem/core/assembly.py,sha256=CTgI5KZhXx5PnvPHMZQRKg0GdhwqNm4EvPggF_SHwAY,46971
4
+ fluxfem/core/basis.py,sha256=Awru1LcXgukQsP5scWn6i6PsqszvIFa_k7UM-ShbThQ,32435
5
+ fluxfem/core/context_types.py,sha256=67Q_qPG8DZ6B6pYN-RzibhNsHBZfhQtkX0kfnfW46Qc,1405
6
+ fluxfem/core/data.py,sha256=_byAZTasIGGwNRU3gqw_ZZR1HMVLJpk9gix2AI3AJWk,1818
7
+ fluxfem/core/dtypes.py,sha256=FnJ98C3yIibaatN-wmLO3ksI6XabA7G3rI_SOxPmko8,251
8
+ fluxfem/core/forms.py,sha256=uC5WxG3h3G7I9FxNRVvA8JLVpJP-QjNZtj8fjxavqVE,7697
9
+ fluxfem/core/interp.py,sha256=v9HzkYgQnEqf6GnB9tXqfrNk0N7YsmPcZBfNGNUU3b8,2004
10
+ fluxfem/core/mixed_assembly.py,sha256=4lL15AsKV4KA-D_mhwc_zXyIhff1fwMkYj4iPWDbDwk,8513
11
+ fluxfem/core/mixed_space.py,sha256=VbQyz1iwrk5-UfvxNmlVHS1mPy5WnCTSzBQXNUbMA68,14203
12
+ fluxfem/core/mixed_weakform.py,sha256=7WmleuB9-o2PFr4Mbwh7Dk19PZ2VNudWoFXlugACd80,2878
13
+ fluxfem/core/solver.py,sha256=OOKiEsW9j4BPCtwgIYyaUHh0Bw5dAd975aGl2izOYqQ,3772
14
+ fluxfem/core/space.py,sha256=DQ2hvqz226lnrKlIHc617LGiwdup_6pgfCx53DgdjWA,23606
15
+ fluxfem/core/weakform.py,sha256=54ntcT-ysR3sVwRS2bgVeP6AslMgIgxVkwi3SrMAKiE,71229
16
+ fluxfem/helpers_ts.py,sha256=T3HCqXniF116lvznq0b7CDUok5_yZZc8l9XtlE81yvg,221
17
+ fluxfem/helpers_wf.py,sha256=pA8bprvbdXZL_qourm07xaJAsGyNnAP8wXmJf8fOj-k,2158
18
+ fluxfem/mesh/__init__.py,sha256=u2CzTjFxj_CRbi18FezIDh73k_lan_3wGBifTkdJH4w,2418
19
+ fluxfem/mesh/base.py,sha256=CAZwHp4lQzVKQe2TiWKG2-ktXWuC7AAURxIPR9pI7rU,22750
20
+ fluxfem/mesh/contact.py,sha256=8Uy2UGaUB7z_3OuRJ8Jdn7DET1Bq-X0GGEV9bn0LYtA,30059
21
+ fluxfem/mesh/dtypes.py,sha256=FnJ98C3yIibaatN-wmLO3ksI6XabA7G3rI_SOxPmko8,251
22
+ fluxfem/mesh/hex.py,sha256=VhH0THJMHPhNtwAvqBjIaeNMzBUd8SWzkih2FcR1NWc,12455
23
+ fluxfem/mesh/io.py,sha256=j6EM7AQ9xiDGAc8I_q9t5vkLIGuuezF3uc1kTvCXmb0,3119
24
+ fluxfem/mesh/mortar.py,sha256=nfy8TyncDmyAgx71E2XNEu4Iv5joLU9Wu8vWVdV3WeM,151395
25
+ fluxfem/mesh/predicate.py,sha256=7O9kcKYg_OPtwhqYVdA-j9LQYtcG2Nl781UupKm6U-A,1505
26
+ fluxfem/mesh/supermesh.py,sha256=bKHERAB4vMkeiuT6wFAoKPKbv-O-8C2crrvJkaRW1ak,10463
27
+ fluxfem/mesh/surface.py,sha256=FJgIvLS8WJElpA7dL9_D2wMh7NZgE0gtfLCBw3g8NJY,11179
28
+ fluxfem/mesh/tet.py,sha256=8ijEdjxOrO4mghIApKqIkOwgcIJKNSIL65uGuYHF1-s,10191
29
+ fluxfem/physics/__init__.py,sha256=gUrVF1FSiSVZezqRGvKSTcZDH79Ty3opiJ9-H1gycqY,1426
30
+ fluxfem/physics/diffusion.py,sha256=T3jIGqnuaoSMB8q9x6qNwY23V55-lQGb6ome_WQnOS8,537
31
+ fluxfem/physics/elasticity/__init__.py,sha256=4pAqAstT9T20pY5q417c9FQAarq_T8g2hpqDtrUDkcw,1061
32
+ fluxfem/physics/elasticity/hyperelastic.py,sha256=S61yQYzu5Njowx9QF2qsMOr8pY7Mz5dIhsW-GPev-90,3964
33
+ fluxfem/physics/elasticity/linear.py,sha256=mUayoQ4buWCkqyWC7NfanNjYtoNFiVyzaQjHdfzEIjs,2413
34
+ fluxfem/physics/elasticity/materials.py,sha256=f2y7_nY3KMSmD2-G4znondAOvh-XDvJD_-zcE2EZcKw,977
35
+ fluxfem/physics/elasticity/stress.py,sha256=1JY4ZKZglcst3Tot7uOvAsaGydJUuwRFFvaft3Fghg8,1181
36
+ fluxfem/physics/operators.py,sha256=cuMNoUFSnBtyjCbR-VANrJapvwWVObVQZDCm0ot5L4Q,3289
37
+ fluxfem/physics/postprocess.py,sha256=A6VQq_XBKd75rZbP_mqLR--zUd3Dw_XQfjYX4PID1_M,4860
38
+ fluxfem/solver/__init__.py,sha256=KIQ0RTyjer-flCewrTGu80IX6d1OKnO1HwIn2JmQVL0,2492
39
+ fluxfem/solver/bc.py,sha256=IJa9WmAkeLu73fmxppEZRXfB-1o_B-9tQ8uKXZHdxFU,16649
40
+ fluxfem/solver/block_matrix.py,sha256=9egC5bZcgx3sDUJpAt4jEPy_GgQ-hArvPWSFLnFos18,10825
41
+ fluxfem/solver/block_system.py,sha256=Fy1AuALQZg7uxpseGVDrzRGBf9EYAjOi0Sj-3rDsAH0,18620
42
+ fluxfem/solver/cg.py,sha256=scydBIRdHXG9QOtRQfQG9pL4ITxjFaTIkdYPHjQEZgM,11826
43
+ fluxfem/solver/dirichlet.py,sha256=0ERvZd1XBySQAWV9n_QY2VZN8xOdaUNOgL-vn2DwUnI,15560
44
+ fluxfem/solver/history.py,sha256=y-37QPJqPFKFBRdWUrng6OwYyHZRRcPaRtF8yuqpnDc,1034
45
+ fluxfem/solver/newton.py,sha256=Q8y2e0M05fgKVx8VCnths0XtWkLSVEbea2dU2hdLJvQ,24184
46
+ fluxfem/solver/petsc.py,sha256=Kk4vxQrfxD5D_wc3z8dFHg-77KH_FaMY2JB4oCM5wLM,15221
47
+ fluxfem/solver/preconditioner.py,sha256=ijnhSA54rUeN1KCpW_SJFlANsR2dccPnC5-n6VEg0MU,3781
48
+ fluxfem/solver/result.py,sha256=DLLyaHVJ9NYotDqFD0IHlhxg9Hbs726bepqCG_59t94,3256
49
+ fluxfem/solver/solve_runner.py,sha256=uBwZpwIeyYXhXFE6Wr1qlywl4z9ExMCoG4Sagsn_D8U,31413
50
+ fluxfem/solver/solver.py,sha256=pkxYOncGkK1t1L9GcZwW4BwDsc31StUFplIK3QS_cYo,6157
51
+ fluxfem/solver/sparse.py,sha256=8Ji1xkWPqLfy2xZv1ejhJhxILeH8G1peh5Lf_X16oxw,12757
52
+ fluxfem/tools/__init__.py,sha256=S7flze8kfHABc0fdhGgdELzKO8aeBCrDbwRUE3aTGpA,95
53
+ fluxfem/tools/jit.py,sha256=x8MS-RWJfafT9A5bhPLa80quR0dYREvikfmWqNHbxBE,1445
54
+ fluxfem/tools/timer.py,sha256=pCL2T4Vi2M00wi5eVey75QGglZVRiZW3i31rL2ll25U,23145
55
+ fluxfem/tools/visualizer.py,sha256=x7i2_ABpXEP4ixPSiqStNM8lR0HZbaAuViCSF7W-p-U,3854
56
+ fluxfem-0.2.1.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
57
+ fluxfem-0.2.1.dist-info/METADATA,sha256=Mi6PAmMFKYpcv9c0NOrcXx6V-DvMYEF45SF0RX_RlNM,11366
58
+ fluxfem-0.2.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
59
+ fluxfem-0.2.1.dist-info/RECORD,,
@@ -1,127 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: fluxfem
3
- Version: 0.1.4
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
-
31
- ## Examples and Features
32
- <table>
33
- <tr>
34
- <td align="center"><b>Example 1: Diffusion</b></td>
35
- <td align="center"><b>Example 2: Neo Neohookean Hyper Elasticity</b></td>
36
- </tr>
37
- <tr>
38
- <td align="center">
39
- <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/diffusion_mms_timeseries.gif" alt="Diffusion-mms" width="400">
40
- </td>
41
- <td align="center">
42
- <img src="https://media.githubusercontent.com/media/kevin-tofu/fluxfem/main/assets/Neo-Hookean-deformedx20000.png" alt="Neo-Hookean" width="400">
43
- </td>
44
- </tr>
45
- </table>
46
-
47
-
48
- ## Features
49
- - Built on JAX, enabling automatic differentiation with grad, jit, vmap, and related transformations.
50
- - Weak-form–centric API that keeps formulations close to code; weak forms are represented as expression trees and compiled to element kernels.
51
- - Two assembly approaches: weak-form-based assembly and a tensor-based (scikit-fem–style) assembly.
52
- - Handles both linear and nonlinear analyses with AD in JAX.
53
-
54
- ## Usage
55
-
56
- This library provides two assembly approaches.
57
-
58
- - A weak-form-based assembly, where the variational form is written and assembled directly.
59
- - A tensor-based assembly, where trial and test functions are represented explicitly as tensors and assembled accordingly (in the style of scikit-fem).
60
- The first approach offers simplicity and convenience, as mathematical expressions can be written almost directly in code.
61
- However, for more complex operations, the second approach can be easier to implement in practice.
62
- This is because the weak-form-based assembly is ultimately transformed into the tensor-based representation internally during computation.
63
-
64
- ## Weak Form Compile Flow
65
- Weak-form expressions are compiled into an evaluation plan and then executed per element.
66
-
67
- ### weak-form-based assembly
68
- ```Python
69
- import fluxfem as ff
70
- import fluxfem.helpers_wf as h_wf
71
-
72
- space = ff.make_hex_space(mesh, dim=3, intorder=2)
73
- D = ff.isotropic_3d_D(1.0, 0.3)
74
- bilinear_form = ff.BilinearForm.volume(
75
- lambda u, v, D: h_wf.ddot(v.sym_grad, h_wf.matmul_std(D, u.sym_grad)) * h_wf.dOmega()
76
- )
77
- K_wf = space.assemble_bilinear_form(
78
- bilinear_form.get_compiled(),
79
- params=D,
80
- )
81
- ```
82
-
83
- ### tensor-based assembly (scikit-fem-style)
84
-
85
- ```Python
86
- import fluxfem as ff
87
- import numpy as np
88
- import fluxfem.helpers_ts as h_ts
89
-
90
- def linear_elasticity_form(ctx: ff.FormContext, D: np.ndarray) -> ff.jnp.ndarray:
91
- Bu = h_ts.sym_grad(ctx.trial)
92
- Bv = h_ts.sym_grad(ctx.test)
93
- return h_ts.ddot(Bv, D, Bu)
94
-
95
-
96
- space = ff.make_hex_space(mesh, dim=3, intorder=2)
97
- D = ff.isotropic_3d_D(1.0, 0.3)
98
- K = space.assemble_bilinear_form(linear_elasticity_form, params=D)
99
- ```
100
-
101
- ## Documentation
102
-
103
-
104
- ## SetUp
105
-
106
- You can install **FluxFEM** either via **pip** or **Poetry**.
107
-
108
- #### Supported Python Versions
109
-
110
- FluxFEM supports **Python 3.11–3.13**:
111
-
112
-
113
- **Choose one of the following methods:**
114
-
115
- ### Using pip
116
- ```bash
117
- pip install fluxfem
118
- ```
119
-
120
- ### Using poetry
121
- ```bash
122
- poetry add fluxfem
123
- ```
124
-
125
- ## Acknowledgements
126
- I acknoldege everythings that made this work possible.
127
-
@@ -1,48 +0,0 @@
1
- fluxfem/__init__.py,sha256=VXd7BM-dOt74bF_W8NumTMlE7lCrz3jTwoCFNZnpDW0,6122
2
- fluxfem/core/__init__.py,sha256=LzHXumR__i656SEmZuGZa09TqTDltTzMIyBBbN1GOKs,8156
3
- fluxfem/core/assembly.py,sha256=yhc14y4XWvmBpiLun2eH9k1mjAsNmpTbHPJS2VJFO3M,25370
4
- fluxfem/core/basis.py,sha256=ZxTQUAEC2UBuvxGhiSqAPjVnUwP_nIptY_b9Wn2etak,32113
5
- fluxfem/core/context_types.py,sha256=QGv1oc_9Crn3vztyPy_uUN0TpmDkgH5HPrhYzZ_kuys,663
6
- fluxfem/core/data.py,sha256=_byAZTasIGGwNRU3gqw_ZZR1HMVLJpk9gix2AI3AJWk,1818
7
- fluxfem/core/dtypes.py,sha256=WQ_wfJW_R8Mty76mS7h-R2xgCokraEWjsUvjeKYmVJU,118
8
- fluxfem/core/forms.py,sha256=qDaN750oiH44aSReVbOISBR9IsWSEnsv1gxHB7We_D0,7374
9
- fluxfem/core/interp.py,sha256=v9HzkYgQnEqf6GnB9tXqfrNk0N7YsmPcZBfNGNUU3b8,2004
10
- fluxfem/core/solver.py,sha256=nNpb90ddZq8Ek6XPerlKzV4YWtC5ZgEcsRv4KeoFIug,3770
11
- fluxfem/core/space.py,sha256=jj4koa6_7lBBtXWGrF1CehOBKWg--uUW_7q8pB2EFCk,13902
12
- fluxfem/core/weakform.py,sha256=ux4gZukZZBMO6vUegjOn_oaQ2l-nwQMO9L2D98LFh6E,41249
13
- fluxfem/helpers_ts.py,sha256=T3HCqXniF116lvznq0b7CDUok5_yZZc8l9XtlE81yvg,221
14
- fluxfem/helpers_wf.py,sha256=InXhYr0WqyibiNWRJllAPf23sluTyaGSJApbv-Yn8b0,632
15
- fluxfem/mesh/__init__.py,sha256=3ECN0qsVzOnEGTHfrWJ2PV7RJUbSboow1ewfpknI4F4,927
16
- fluxfem/mesh/base.py,sha256=cxfv-m-0qQq3UL4aM0YUJEiAyVrKmtSszwe8rE7PQyQ,10448
17
- fluxfem/mesh/hex.py,sha256=diFF6AngLpA9OllbaPAT00P_0YR4vMVgpc04_IqOLv8,12420
18
- fluxfem/mesh/io.py,sha256=3Nx5WLFP9gG_Ruks4F7jSTVGnc_i5qcxkLBQkQhsmhk,2984
19
- fluxfem/mesh/predicate.py,sha256=7O9kcKYg_OPtwhqYVdA-j9LQYtcG2Nl781UupKm6U-A,1505
20
- fluxfem/mesh/surface.py,sha256=mmtePb1ptd9BSbD79oyPnQwiKadpyVO41xSHDr2XylE,9176
21
- fluxfem/mesh/tet.py,sha256=Yjmx_2UsCxO_rl0Jr60au5zccBVWLJvAaGEzhLCi_LA,9768
22
- fluxfem/physics/__init__.py,sha256=gUrVF1FSiSVZezqRGvKSTcZDH79Ty3opiJ9-H1gycqY,1426
23
- fluxfem/physics/diffusion.py,sha256=gBRKMuhWGnp7wSlbqYKn2WDKvBrVdtCQKV8-qBabmw4,462
24
- fluxfem/physics/elasticity/__init__.py,sha256=4pAqAstT9T20pY5q417c9FQAarq_T8g2hpqDtrUDkcw,1061
25
- fluxfem/physics/elasticity/hyperelastic.py,sha256=uDZIgSeVJ1JgIf5aEFzFyng6qcDHP-seoHNH_aUA4Zg,3364
26
- fluxfem/physics/elasticity/linear.py,sha256=upiX8Qq5v8J0Y-Lhq8OsIFnwQ_AnJc9nJj0g0vWeNcg,2074
27
- fluxfem/physics/elasticity/materials.py,sha256=f2y7_nY3KMSmD2-G4znondAOvh-XDvJD_-zcE2EZcKw,977
28
- fluxfem/physics/elasticity/stress.py,sha256=i3TypnLB-Hhd3UsV2tftOCjF1-KNNpnVEy8rYqT2wIM,1135
29
- fluxfem/physics/operators.py,sha256=LgEvtcDvhskd7BokVsX_wtzceoI2zrLYyB5HWsUBFg4,3009
30
- fluxfem/physics/postprocess.py,sha256=7NKcSJO_Himw1WTJgM4YWxf1KkjGuBwojxY_0Vwy9Ow,4418
31
- fluxfem/solver/__init__.py,sha256=WkQRDWVIxqXuRGrbizl0KVkr7a_yY0jWlsTDI66gaiE,1133
32
- fluxfem/solver/bc.py,sha256=EYrvQbTMQG2WxHbJYJD2nefxwrpiGS7p8ant6R3APgU,15555
33
- fluxfem/solver/cg.py,sha256=3fLtK3oUpR7lQtRPPtE64-PHUjeIp3pDuMZZqVdCXfk,8974
34
- fluxfem/solver/dirichlet.py,sha256=MCXgpJ9lAF7NrK2NeuCxVWgOVfCiPeswIYhbadkwh-Q,3982
35
- fluxfem/solver/history.py,sha256=HhKSmo2B1GaBYEsrifxQxeaeRMiaqm5f6g6DNz5Qb0U,764
36
- fluxfem/solver/newton.py,sha256=aeSQ1ET9dc-xU6HJWn6KNrEg0FA49nSXsoaYuW5BTvM,16251
37
- fluxfem/solver/result.py,sha256=LDtazqofyBmA0pd3zE5eadgKwW053HRcOwJ5k7ClbsA,2357
38
- fluxfem/solver/solve_runner.py,sha256=MCwmHUKnJCX_mFDPFKNp-_yMbviWln5s56ENWZvOj4c,20974
39
- fluxfem/solver/solver.py,sha256=kqXz2qW50gyyFQagUePgNiFcgsLVA94H99_8sHZWiyo,5162
40
- fluxfem/solver/sparse.py,sha256=wyT_XBIMYD2Nrw_ko8FkaPzLWnLm25M41wF2Z2YAbZk,7550
41
- fluxfem/tools/__init__.py,sha256=S7flze8kfHABc0fdhGgdELzKO8aeBCrDbwRUE3aTGpA,95
42
- fluxfem/tools/jit.py,sha256=WVThoNs2XD8ZVCeyLjBgbFaZXHot5RK_RNzvvAjSaew,1110
43
- fluxfem/tools/timer.py,sha256=fvMrKqjOT2S_DoGlTYC5L5TtBnoLS4zyiAZtJVJGt0o,22848
44
- fluxfem/tools/visualizer.py,sha256=aDqSgtX9xOu120-zCzJfwlCOUmxjL_kJ6kAvj27-H14,3733
45
- fluxfem-0.1.4.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
46
- fluxfem-0.1.4.dist-info/METADATA,sha256=hn8uJc3N47pozgegKrVvXCbdFhTQX6sbuLLdpnhQT7U,4463
47
- fluxfem-0.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
48
- fluxfem-0.1.4.dist-info/RECORD,,