fluxfem 0.1.1a0__py3-none-any.whl → 0.1.4__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.
fluxfem/__init__.py CHANGED
@@ -1,159 +1,6 @@
1
- from .core import (
2
- FESpaceBase,
3
- FESpace,
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()
fluxfem/core/__init__.py CHANGED
@@ -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,
@@ -86,6 +88,8 @@ from .weakform import (
86
88
  transpose,
87
89
  log,
88
90
  transpose_last2,
91
+ matmul,
92
+ matmul_std,
89
93
  einsum,
90
94
  )
91
95
  from ..mesh import (
@@ -121,39 +125,56 @@ from .basis import (
121
125
  TetQuadraticBasis10,
122
126
  TetQuadraticBasis10Pytree,
123
127
  )
128
+ import importlib
129
+
124
130
  from ..physics import lame_parameters, isotropic_3d_D
125
131
  from .solver import spdirect_solve_cpu, spdirect_solve_gpu, spdirect_solve_jax, coo_to_csr
126
- from ..solver import (
127
- SparsityPattern,
128
- FluxSparseMatrix,
129
- LinearSolver,
130
- NonlinearSolver,
131
- enforce_dirichlet_dense,
132
- enforce_dirichlet_sparse,
133
- free_dofs,
134
- condense_dirichlet_fluxsparse,
135
- condense_dirichlet_dense,
136
- expand_dirichlet_solution,
137
- cg_solve,
138
- cg_solve_jax,
139
- NonlinearAnalysis,
140
- NewtonLoopConfig,
141
- LoadStepResult,
142
- NewtonSolveRunner,
143
- solve_nonlinear,
144
- LinearAnalysis,
145
- LinearSolveConfig,
146
- LinearStepResult,
147
- LinearSolveRunner,
148
- newton_solve,
149
- )
150
- from ..solver.bc import (
151
- SurfaceFormField,
152
- SurfaceFormContext,
153
- vector_surface_load_form,
154
- make_vector_surface_load_form,
155
- assemble_surface_linear_form,
156
- )
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
157
178
 
158
179
  __all__ = [
159
180
  "FESpace",
@@ -161,6 +182,10 @@ __all__ = [
161
182
  "FESpacePytree",
162
183
  "FormContext",
163
184
  "MixedFormContext",
185
+ "VolumeContext",
186
+ "SurfaceContext",
187
+ "VolumeContext",
188
+ "SurfaceContext",
164
189
  "FieldPair",
165
190
  "ElementVector",
166
191
  "vector_load_form",
@@ -229,6 +254,7 @@ __all__ = [
229
254
  "compile_mixed_residual",
230
255
  "grad",
231
256
  "sym_grad",
257
+ "outer",
232
258
  "dot",
233
259
  "sdot",
234
260
  "ddot",
@@ -244,6 +270,8 @@ __all__ = [
244
270
  "transpose",
245
271
  "log",
246
272
  "transpose_last2",
273
+ "matmul",
274
+ "matmul_std",
247
275
  "einsum",
248
276
  "HexMesh",
249
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
fluxfem/core/forms.py CHANGED
@@ -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
- FormFieldLike = ScalarFormField | VectorFormField
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: