fluxfem 0.1.3__tar.gz → 0.1.4__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.
- {fluxfem-0.1.3 → fluxfem-0.1.4}/PKG-INFO +13 -11
- {fluxfem-0.1.3 → fluxfem-0.1.4}/README.md +10 -8
- {fluxfem-0.1.3 → fluxfem-0.1.4}/pyproject.toml +6 -6
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/__init__.py +68 -161
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/__init__.py +57 -31
- fluxfem-0.1.4/src/fluxfem/core/context_types.py +36 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/forms.py +5 -1
- fluxfem-0.1.4/src/fluxfem/core/weakform.py +1258 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/helpers_wf.py +4 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/base.py +6 -1
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/hex.py +1 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/io.py +2 -0
- fluxfem-0.1.3/src/fluxfem/core/weakform.py +0 -828
- {fluxfem-0.1.3 → fluxfem-0.1.4}/LICENSE +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/assembly.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/basis.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/data.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/dtypes.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/interp.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/solver.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/core/space.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/helpers_ts.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/__init__.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/predicate.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/surface.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/mesh/tet.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/__init__.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/diffusion.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/elasticity/__init__.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/elasticity/hyperelastic.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/elasticity/linear.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/elasticity/materials.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/elasticity/stress.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/operators.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/physics/postprocess.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/__init__.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/bc.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/cg.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/dirichlet.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/history.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/newton.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/result.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/solve_runner.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/solver.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/solver/sparse.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/tools/__init__.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/tools/jit.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/tools/timer.py +0 -0
- {fluxfem-0.1.3 → fluxfem-0.1.4}/src/fluxfem/tools/visualizer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: fluxfem
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: FluxFEM: A weak-form-centric differentiable finite element framework in JAX
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: Kohei Watanabe
|
|
@@ -10,8 +10,8 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
-
Requires-Dist: jax (
|
|
14
|
-
Requires-Dist: jaxlib (
|
|
13
|
+
Requires-Dist: jax (>=0.8.2,<0.9.0)
|
|
14
|
+
Requires-Dist: jaxlib (>=0.8.2,<0.9.0)
|
|
15
15
|
Requires-Dist: matplotlib (>=3.10.7,<4.0.0)
|
|
16
16
|
Requires-Dist: meshio (>=5.3.5,<6.0.0)
|
|
17
17
|
Requires-Dist: pyvista (>=0.46.4,<0.47.0)
|
|
@@ -22,6 +22,8 @@ Description-Content-Type: text/markdown
|
|
|
22
22
|
[](https://pypi.org/project/fluxfem/)
|
|
23
23
|

|
|
24
24
|

|
|
25
|
+
[](https://doi.org/10.5281/zenodo.18055465)
|
|
26
|
+
|
|
25
27
|
|
|
26
28
|
# FluxFEM
|
|
27
29
|
A weak-form-centric differentiable finite element framework in JAX
|
|
@@ -44,13 +46,10 @@ Description-Content-Type: text/markdown
|
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
## Features
|
|
47
|
-
- Built on JAX, enabling automatic differentiation
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
- Supports two assembly approaches: weak-form-based assembly and a tensor-based (scikit-fem–style) assembly.
|
|
52
|
-
|
|
53
|
-
- enables to handle both Linear / Non-Linear analysis with AD in JAX
|
|
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.
|
|
54
53
|
|
|
55
54
|
## Usage
|
|
56
55
|
|
|
@@ -62,6 +61,9 @@ The first approach offers simplicity and convenience, as mathematical expression
|
|
|
62
61
|
However, for more complex operations, the second approach can be easier to implement in practice.
|
|
63
62
|
This is because the weak-form-based assembly is ultimately transformed into the tensor-based representation internally during computation.
|
|
64
63
|
|
|
64
|
+
## Weak Form Compile Flow
|
|
65
|
+
Weak-form expressions are compiled into an evaluation plan and then executed per element.
|
|
66
|
+
|
|
65
67
|
### weak-form-based assembly
|
|
66
68
|
```Python
|
|
67
69
|
import fluxfem as ff
|
|
@@ -70,7 +72,7 @@ import fluxfem.helpers_wf as h_wf
|
|
|
70
72
|
space = ff.make_hex_space(mesh, dim=3, intorder=2)
|
|
71
73
|
D = ff.isotropic_3d_D(1.0, 0.3)
|
|
72
74
|
bilinear_form = ff.BilinearForm.volume(
|
|
73
|
-
lambda u, v, D: h_wf.ddot(v.sym_grad, D
|
|
75
|
+
lambda u, v, D: h_wf.ddot(v.sym_grad, h_wf.matmul_std(D, u.sym_grad)) * h_wf.dOmega()
|
|
74
76
|
)
|
|
75
77
|
K_wf = space.assemble_bilinear_form(
|
|
76
78
|
bilinear_form.get_compiled(),
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
[](https://pypi.org/project/fluxfem/)
|
|
4
4
|

|
|
5
5
|

|
|
6
|
+
[](https://doi.org/10.5281/zenodo.18055465)
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
# FluxFEM
|
|
8
10
|
A weak-form-centric differentiable finite element framework in JAX
|
|
@@ -25,13 +27,10 @@
|
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
## Features
|
|
28
|
-
- Built on JAX, enabling automatic differentiation
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
- Supports two assembly approaches: weak-form-based assembly and a tensor-based (scikit-fem–style) assembly.
|
|
33
|
-
|
|
34
|
-
- enables to handle both Linear / Non-Linear analysis with AD in JAX
|
|
30
|
+
- Built on JAX, enabling automatic differentiation with grad, jit, vmap, and related transformations.
|
|
31
|
+
- Weak-form–centric API that keeps formulations close to code; weak forms are represented as expression trees and compiled to element kernels.
|
|
32
|
+
- Two assembly approaches: weak-form-based assembly and a tensor-based (scikit-fem–style) assembly.
|
|
33
|
+
- Handles both linear and nonlinear analyses with AD in JAX.
|
|
35
34
|
|
|
36
35
|
## Usage
|
|
37
36
|
|
|
@@ -43,6 +42,9 @@ The first approach offers simplicity and convenience, as mathematical expression
|
|
|
43
42
|
However, for more complex operations, the second approach can be easier to implement in practice.
|
|
44
43
|
This is because the weak-form-based assembly is ultimately transformed into the tensor-based representation internally during computation.
|
|
45
44
|
|
|
45
|
+
## Weak Form Compile Flow
|
|
46
|
+
Weak-form expressions are compiled into an evaluation plan and then executed per element.
|
|
47
|
+
|
|
46
48
|
### weak-form-based assembly
|
|
47
49
|
```Python
|
|
48
50
|
import fluxfem as ff
|
|
@@ -51,7 +53,7 @@ import fluxfem.helpers_wf as h_wf
|
|
|
51
53
|
space = ff.make_hex_space(mesh, dim=3, intorder=2)
|
|
52
54
|
D = ff.isotropic_3d_D(1.0, 0.3)
|
|
53
55
|
bilinear_form = ff.BilinearForm.volume(
|
|
54
|
-
lambda u, v, D: h_wf.ddot(v.sym_grad, D
|
|
56
|
+
lambda u, v, D: h_wf.ddot(v.sym_grad, h_wf.matmul_std(D, u.sym_grad)) * h_wf.dOmega()
|
|
55
57
|
)
|
|
56
58
|
K_wf = space.assemble_bilinear_form(
|
|
57
59
|
bilinear_form.get_compiled(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fluxfem"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.4"
|
|
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 (
|
|
22
|
-
"jaxlib (
|
|
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.
|
|
27
|
+
version = "0.1.4"
|
|
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 = "
|
|
43
|
-
jaxlib = "
|
|
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]
|
|
@@ -1,159 +1,6 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
FESpacePytree,
|
|
5
|
-
Expr,
|
|
6
|
-
FieldRef,
|
|
7
|
-
ParamRef,
|
|
8
|
-
trial_ref,
|
|
9
|
-
test_ref,
|
|
10
|
-
unknown_ref,
|
|
11
|
-
Params,
|
|
12
|
-
LinearForm,
|
|
13
|
-
BilinearForm,
|
|
14
|
-
ResidualForm,
|
|
15
|
-
MixedWeakForm,
|
|
16
|
-
compile_bilinear,
|
|
17
|
-
compile_linear,
|
|
18
|
-
compile_residual,
|
|
19
|
-
compile_surface_linear,
|
|
20
|
-
compile_mixed_residual,
|
|
21
|
-
sdot,
|
|
22
|
-
dOmega,
|
|
23
|
-
FormContext,
|
|
24
|
-
MixedFormContext,
|
|
25
|
-
FieldPair,
|
|
26
|
-
ElementVector,
|
|
27
|
-
vector_load_form,
|
|
28
|
-
make_space,
|
|
29
|
-
make_space_pytree,
|
|
30
|
-
make_hex_basis,
|
|
31
|
-
make_hex_basis_pytree,
|
|
32
|
-
make_hex_space,
|
|
33
|
-
make_hex_space_pytree,
|
|
34
|
-
make_hex20_basis,
|
|
35
|
-
make_hex20_basis_pytree,
|
|
36
|
-
make_hex20_space,
|
|
37
|
-
make_hex20_space_pytree,
|
|
38
|
-
make_hex27_basis,
|
|
39
|
-
make_hex27_basis_pytree,
|
|
40
|
-
make_hex27_space,
|
|
41
|
-
make_hex27_space_pytree,
|
|
42
|
-
make_tet_basis,
|
|
43
|
-
make_tet_basis_pytree,
|
|
44
|
-
make_tet_space,
|
|
45
|
-
make_tet_space_pytree,
|
|
46
|
-
make_tet10_basis,
|
|
47
|
-
make_tet10_basis_pytree,
|
|
48
|
-
make_tet10_space,
|
|
49
|
-
make_tet10_space_pytree,
|
|
50
|
-
make_element_residual_kernel,
|
|
51
|
-
make_element_jacobian_kernel,
|
|
52
|
-
element_residual,
|
|
53
|
-
element_jacobian,
|
|
54
|
-
make_sparsity_pattern,
|
|
55
|
-
assemble_functional,
|
|
56
|
-
assemble_mass_matrix,
|
|
57
|
-
scalar_body_force_form,
|
|
58
|
-
make_scalar_body_force_form,
|
|
59
|
-
constant_body_force_form,
|
|
60
|
-
vector_body_force_form,
|
|
61
|
-
BaseMeshPytree,
|
|
62
|
-
bbox_predicate,
|
|
63
|
-
plane_predicate,
|
|
64
|
-
axis_plane_predicate,
|
|
65
|
-
slab_predicate,
|
|
66
|
-
HexMesh,
|
|
67
|
-
HexMeshPytree,
|
|
68
|
-
StructuredHexBox,
|
|
69
|
-
SurfaceMesh,
|
|
70
|
-
SurfaceMeshPytree,
|
|
71
|
-
load_gmsh_mesh,
|
|
72
|
-
load_gmsh_hex_mesh,
|
|
73
|
-
load_gmsh_tet_mesh,
|
|
74
|
-
make_surface_from_facets,
|
|
75
|
-
TetMesh,
|
|
76
|
-
TetMeshPytree,
|
|
77
|
-
StructuredTetBox,
|
|
78
|
-
StructuredTetTensorBox,
|
|
79
|
-
tag_axis_minmax_facets,
|
|
80
|
-
HexTriLinearBasis,
|
|
81
|
-
HexTriLinearBasisPytree,
|
|
82
|
-
HexSerendipityBasis20,
|
|
83
|
-
HexSerendipityBasis20Pytree,
|
|
84
|
-
HexTriQuadraticBasis27,
|
|
85
|
-
HexTriQuadraticBasis27Pytree,
|
|
86
|
-
TetLinearBasis,
|
|
87
|
-
TetLinearBasisPytree,
|
|
88
|
-
TetQuadraticBasis10,
|
|
89
|
-
TetQuadraticBasis10Pytree,
|
|
90
|
-
MeshData,
|
|
91
|
-
BasisData,
|
|
92
|
-
SpaceData,
|
|
93
|
-
MeshData,
|
|
94
|
-
BasisData,
|
|
95
|
-
SpaceData,
|
|
96
|
-
lame_parameters,
|
|
97
|
-
isotropic_3d_D,
|
|
98
|
-
spdirect_solve_cpu,
|
|
99
|
-
spdirect_solve_gpu,
|
|
100
|
-
spdirect_solve_jax,
|
|
101
|
-
coo_to_csr,
|
|
102
|
-
SparsityPattern,
|
|
103
|
-
FluxSparseMatrix,
|
|
104
|
-
LinearSolver,
|
|
105
|
-
NonlinearSolver,
|
|
106
|
-
enforce_dirichlet_dense,
|
|
107
|
-
enforce_dirichlet_sparse,
|
|
108
|
-
free_dofs,
|
|
109
|
-
condense_dirichlet_fluxsparse,
|
|
110
|
-
condense_dirichlet_dense,
|
|
111
|
-
expand_dirichlet_solution,
|
|
112
|
-
cg_solve,
|
|
113
|
-
cg_solve_jax,
|
|
114
|
-
NonlinearAnalysis,
|
|
115
|
-
NewtonLoopConfig,
|
|
116
|
-
LoadStepResult,
|
|
117
|
-
NewtonSolveRunner,
|
|
118
|
-
solve_nonlinear,
|
|
119
|
-
LinearAnalysis,
|
|
120
|
-
LinearSolveConfig,
|
|
121
|
-
LinearStepResult,
|
|
122
|
-
LinearSolveRunner,
|
|
123
|
-
newton_solve,
|
|
124
|
-
SurfaceFormField,
|
|
125
|
-
SurfaceFormContext,
|
|
126
|
-
vector_surface_load_form,
|
|
127
|
-
make_vector_surface_load_form,
|
|
128
|
-
assemble_surface_linear_form,
|
|
129
|
-
)
|
|
130
|
-
from .tools.visualizer import write_vtu, write_displacement_vtu
|
|
131
|
-
from .tools.jit import make_jitted_residual, make_jitted_jacobian
|
|
132
|
-
from .physics import (
|
|
133
|
-
linear_elasticity_form,
|
|
134
|
-
vector_body_force_form,
|
|
135
|
-
constant_body_force_vector_form,
|
|
136
|
-
diffusion_form,
|
|
137
|
-
dot,
|
|
138
|
-
ddot,
|
|
139
|
-
transpose_last2,
|
|
140
|
-
sym_grad,
|
|
141
|
-
sym_grad_u,
|
|
142
|
-
right_cauchy_green,
|
|
143
|
-
green_lagrange_strain,
|
|
144
|
-
deformation_gradient,
|
|
145
|
-
pk2_neo_hookean,
|
|
146
|
-
neo_hookean_residual_form,
|
|
147
|
-
make_elastic_point_data,
|
|
148
|
-
write_elastic_vtu,
|
|
149
|
-
make_point_data_displacement,
|
|
150
|
-
write_point_data_vtu,
|
|
151
|
-
interpolate_at_points,
|
|
152
|
-
principal_stresses,
|
|
153
|
-
principal_sum,
|
|
154
|
-
max_shear_stress,
|
|
155
|
-
von_mises_stress,
|
|
156
|
-
)
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
157
4
|
|
|
158
5
|
__all__ = [
|
|
159
6
|
"FESpaceBase",
|
|
@@ -175,10 +22,13 @@ __all__ = [
|
|
|
175
22
|
"compile_residual",
|
|
176
23
|
"compile_surface_linear",
|
|
177
24
|
"compile_mixed_residual",
|
|
25
|
+
"outer",
|
|
178
26
|
"sdot",
|
|
179
27
|
"dOmega",
|
|
180
28
|
"FormContext",
|
|
181
29
|
"MixedFormContext",
|
|
30
|
+
"VolumeContext",
|
|
31
|
+
"SurfaceContext",
|
|
182
32
|
"FieldPair",
|
|
183
33
|
"ElementVector",
|
|
184
34
|
"vector_load_form",
|
|
@@ -243,6 +93,7 @@ __all__ = [
|
|
|
243
93
|
"vector_surface_load_form",
|
|
244
94
|
"make_vector_surface_load_form",
|
|
245
95
|
"assemble_surface_linear_form",
|
|
96
|
+
"tag_axis_minmax_facets",
|
|
246
97
|
"load_gmsh_mesh",
|
|
247
98
|
"load_gmsh_hex_mesh",
|
|
248
99
|
"load_gmsh_tet_mesh",
|
|
@@ -307,11 +158,71 @@ __all__ = [
|
|
|
307
158
|
"von_mises_stress",
|
|
308
159
|
]
|
|
309
160
|
|
|
161
|
+
_PHYSICS_EXPORTS = {
|
|
162
|
+
"lame_parameters",
|
|
163
|
+
"isotropic_3d_D",
|
|
164
|
+
"linear_elasticity_form",
|
|
165
|
+
"vector_body_force_form",
|
|
166
|
+
"constant_body_force_vector_form",
|
|
167
|
+
"diffusion_form",
|
|
168
|
+
"dot",
|
|
169
|
+
"ddot",
|
|
170
|
+
"transpose_last2",
|
|
171
|
+
"sym_grad",
|
|
172
|
+
"sym_grad_u",
|
|
173
|
+
"right_cauchy_green",
|
|
174
|
+
"green_lagrange_strain",
|
|
175
|
+
"deformation_gradient",
|
|
176
|
+
"pk2_neo_hookean",
|
|
177
|
+
"neo_hookean_residual_form",
|
|
178
|
+
"make_elastic_point_data",
|
|
179
|
+
"write_elastic_vtu",
|
|
180
|
+
"make_point_data_displacement",
|
|
181
|
+
"write_point_data_vtu",
|
|
182
|
+
"interpolate_at_points",
|
|
183
|
+
"principal_stresses",
|
|
184
|
+
"principal_sum",
|
|
185
|
+
"max_shear_stress",
|
|
186
|
+
"von_mises_stress",
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
_TOOLS_VIS_EXPORTS = {
|
|
190
|
+
"write_vtu",
|
|
191
|
+
"write_displacement_vtu",
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
_TOOLS_JIT_EXPORTS = {
|
|
195
|
+
"make_jitted_residual",
|
|
196
|
+
"make_jitted_jacobian",
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_CORE_EXPORTS = set(__all__) - _PHYSICS_EXPORTS - _TOOLS_VIS_EXPORTS - _TOOLS_JIT_EXPORTS
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def __getattr__(name: str):
|
|
203
|
+
if name in _PHYSICS_EXPORTS:
|
|
204
|
+
module = importlib.import_module(".physics", __name__)
|
|
205
|
+
elif name in _TOOLS_VIS_EXPORTS:
|
|
206
|
+
module = importlib.import_module(".tools.visualizer", __name__)
|
|
207
|
+
elif name in _TOOLS_JIT_EXPORTS:
|
|
208
|
+
module = importlib.import_module(".tools.jit", __name__)
|
|
209
|
+
elif name in _CORE_EXPORTS:
|
|
210
|
+
module = importlib.import_module(".core", __name__)
|
|
211
|
+
else:
|
|
212
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
213
|
+
|
|
214
|
+
value = getattr(module, name)
|
|
215
|
+
globals()[name] = value
|
|
216
|
+
return value
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def __dir__():
|
|
220
|
+
return sorted(set(globals()) | set(__all__))
|
|
221
|
+
|
|
310
222
|
|
|
311
223
|
try:
|
|
312
224
|
from importlib.metadata import version, PackageNotFoundError
|
|
313
225
|
except ImportError:
|
|
314
|
-
# old python
|
|
315
226
|
from importlib_metadata import version, PackageNotFoundError
|
|
316
227
|
|
|
317
228
|
|
|
@@ -320,21 +231,17 @@ def read_version_from_pyproject():
|
|
|
320
231
|
import re
|
|
321
232
|
|
|
322
233
|
root = pathlib.Path(__file__).resolve().parent.parent
|
|
323
|
-
# while root != root.parent and depth < max_depth:
|
|
324
234
|
pyproject_path = root / "pyproject.toml"
|
|
325
235
|
if pyproject_path.exists():
|
|
326
236
|
content = pyproject_path.read_text()
|
|
327
237
|
match = re.search(r'version\s*=\s*"(.*?)"', content)
|
|
328
238
|
if match:
|
|
329
239
|
return match.group(1)
|
|
330
|
-
# root = root.parent
|
|
331
|
-
# depth += 1
|
|
332
240
|
return "0.0.0"
|
|
333
241
|
|
|
334
242
|
|
|
335
243
|
def get_version(package_name):
|
|
336
244
|
try:
|
|
337
|
-
# print("version-", version(package_name))
|
|
338
245
|
return version(package_name)
|
|
339
246
|
except PackageNotFoundError:
|
|
340
247
|
return read_version_from_pyproject()
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .forms import FormContext, MixedFormContext, FieldPair, ElementVector, vector_load_form
|
|
2
|
+
from .context_types import VolumeContext, SurfaceContext
|
|
2
3
|
from .space import (
|
|
3
4
|
FESpaceBase,
|
|
4
5
|
FESpace,
|
|
@@ -71,6 +72,7 @@ from .weakform import (
|
|
|
71
72
|
compile_mixed_residual,
|
|
72
73
|
grad,
|
|
73
74
|
sym_grad,
|
|
75
|
+
outer,
|
|
74
76
|
dot,
|
|
75
77
|
sdot,
|
|
76
78
|
ddot,
|
|
@@ -87,6 +89,7 @@ from .weakform import (
|
|
|
87
89
|
log,
|
|
88
90
|
transpose_last2,
|
|
89
91
|
matmul,
|
|
92
|
+
matmul_std,
|
|
90
93
|
einsum,
|
|
91
94
|
)
|
|
92
95
|
from ..mesh import (
|
|
@@ -122,39 +125,56 @@ from .basis import (
|
|
|
122
125
|
TetQuadraticBasis10,
|
|
123
126
|
TetQuadraticBasis10Pytree,
|
|
124
127
|
)
|
|
128
|
+
import importlib
|
|
129
|
+
|
|
125
130
|
from ..physics import lame_parameters, isotropic_3d_D
|
|
126
131
|
from .solver import spdirect_solve_cpu, spdirect_solve_gpu, spdirect_solve_jax, coo_to_csr
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
132
|
+
|
|
133
|
+
_SOLVER_EXPORTS = {
|
|
134
|
+
"SparsityPattern",
|
|
135
|
+
"FluxSparseMatrix",
|
|
136
|
+
"LinearSolver",
|
|
137
|
+
"NonlinearSolver",
|
|
138
|
+
"enforce_dirichlet_dense",
|
|
139
|
+
"enforce_dirichlet_sparse",
|
|
140
|
+
"free_dofs",
|
|
141
|
+
"condense_dirichlet_fluxsparse",
|
|
142
|
+
"condense_dirichlet_dense",
|
|
143
|
+
"expand_dirichlet_solution",
|
|
144
|
+
"cg_solve",
|
|
145
|
+
"cg_solve_jax",
|
|
146
|
+
"NonlinearAnalysis",
|
|
147
|
+
"NewtonLoopConfig",
|
|
148
|
+
"LoadStepResult",
|
|
149
|
+
"NewtonSolveRunner",
|
|
150
|
+
"solve_nonlinear",
|
|
151
|
+
"LinearAnalysis",
|
|
152
|
+
"LinearSolveConfig",
|
|
153
|
+
"LinearStepResult",
|
|
154
|
+
"LinearSolveRunner",
|
|
155
|
+
"newton_solve",
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
_SOLVER_BC_EXPORTS = {
|
|
159
|
+
"SurfaceFormField",
|
|
160
|
+
"SurfaceFormContext",
|
|
161
|
+
"vector_surface_load_form",
|
|
162
|
+
"make_vector_surface_load_form",
|
|
163
|
+
"assemble_surface_linear_form",
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def __getattr__(name: str):
|
|
168
|
+
if name in _SOLVER_EXPORTS:
|
|
169
|
+
module = importlib.import_module("..solver", __name__)
|
|
170
|
+
elif name in _SOLVER_BC_EXPORTS:
|
|
171
|
+
module = importlib.import_module("..solver.bc", __name__)
|
|
172
|
+
else:
|
|
173
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
174
|
+
|
|
175
|
+
value = getattr(module, name)
|
|
176
|
+
globals()[name] = value
|
|
177
|
+
return value
|
|
158
178
|
|
|
159
179
|
__all__ = [
|
|
160
180
|
"FESpace",
|
|
@@ -162,6 +182,10 @@ __all__ = [
|
|
|
162
182
|
"FESpacePytree",
|
|
163
183
|
"FormContext",
|
|
164
184
|
"MixedFormContext",
|
|
185
|
+
"VolumeContext",
|
|
186
|
+
"SurfaceContext",
|
|
187
|
+
"VolumeContext",
|
|
188
|
+
"SurfaceContext",
|
|
165
189
|
"FieldPair",
|
|
166
190
|
"ElementVector",
|
|
167
191
|
"vector_load_form",
|
|
@@ -230,6 +254,7 @@ __all__ = [
|
|
|
230
254
|
"compile_mixed_residual",
|
|
231
255
|
"grad",
|
|
232
256
|
"sym_grad",
|
|
257
|
+
"outer",
|
|
233
258
|
"dot",
|
|
234
259
|
"sdot",
|
|
235
260
|
"ddot",
|
|
@@ -246,6 +271,7 @@ __all__ = [
|
|
|
246
271
|
"log",
|
|
247
272
|
"transpose_last2",
|
|
248
273
|
"matmul",
|
|
274
|
+
"matmul_std",
|
|
249
275
|
"einsum",
|
|
250
276
|
"HexMesh",
|
|
251
277
|
"HexMeshPytree",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Protocol, TypeAlias, runtime_checkable
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@runtime_checkable
|
|
7
|
+
class VolumeContext(Protocol):
|
|
8
|
+
"""Minimum interface for volume weak-form evaluation."""
|
|
9
|
+
|
|
10
|
+
test: Any
|
|
11
|
+
trial: Any
|
|
12
|
+
w: Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@runtime_checkable
|
|
16
|
+
class SurfaceContext(Protocol):
|
|
17
|
+
"""Minimum interface for surface weak-form evaluation."""
|
|
18
|
+
|
|
19
|
+
v: Any
|
|
20
|
+
w: Any
|
|
21
|
+
detJ: Any
|
|
22
|
+
normal: Any
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@runtime_checkable
|
|
26
|
+
class FormFieldLike(Protocol):
|
|
27
|
+
"""Minimum interface for form fields used in weak-form evaluation."""
|
|
28
|
+
|
|
29
|
+
N: Any
|
|
30
|
+
gradN: Any
|
|
31
|
+
detJ: Any
|
|
32
|
+
value_dim: int
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
UElement: TypeAlias = Any
|
|
36
|
+
ParamsLike: TypeAlias = Any
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import jax
|
|
4
4
|
import jax.numpy as jnp
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, TypeAlias
|
|
6
7
|
|
|
7
8
|
from .basis import Basis3D
|
|
8
9
|
|
|
@@ -119,7 +120,10 @@ class VectorFormField:
|
|
|
119
120
|
return cls(N, elem_coords, aux["basis"], aux["value_dim"], gradN, detJ)
|
|
120
121
|
|
|
121
122
|
|
|
122
|
-
|
|
123
|
+
if TYPE_CHECKING:
|
|
124
|
+
FormFieldLike: TypeAlias = ScalarFormField | VectorFormField
|
|
125
|
+
else:
|
|
126
|
+
FormFieldLike = object
|
|
123
127
|
|
|
124
128
|
|
|
125
129
|
def vector_load_form(field: FormFieldLike, load_vec: jnp.ndarray) -> jnp.ndarray:
|