lsdo-function-spaces 1.0.0__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 (40) hide show
  1. lsdo_function_spaces/__init__.py +64 -0
  2. lsdo_function_spaces/core/__init__.py +0 -0
  3. lsdo_function_spaces/core/function.py +1322 -0
  4. lsdo_function_spaces/core/function_set.py +1081 -0
  5. lsdo_function_spaces/core/function_set_space.py +379 -0
  6. lsdo_function_spaces/core/function_space.py +482 -0
  7. lsdo_function_spaces/core/operations/__init__.py +0 -0
  8. lsdo_function_spaces/core/operations/basic_ops.py +85 -0
  9. lsdo_function_spaces/core/operations/operations.py +5 -0
  10. lsdo_function_spaces/core/optimization.py +183 -0
  11. lsdo_function_spaces/core/spaces/__init__.py +0 -0
  12. lsdo_function_spaces/core/spaces/b_spline_space.py +418 -0
  13. lsdo_function_spaces/core/spaces/conditional_space.py +65 -0
  14. lsdo_function_spaces/core/spaces/constant_space.py +57 -0
  15. lsdo_function_spaces/core/spaces/idw_space.py +271 -0
  16. lsdo_function_spaces/core/spaces/non_cython_bsplines/__init__.py +0 -0
  17. lsdo_function_spaces/core/spaces/non_cython_bsplines/b_spline_csdl_custom_ops.py +420 -0
  18. lsdo_function_spaces/core/spaces/non_cython_bsplines/b_spline_patch_projection.py +1022 -0
  19. lsdo_function_spaces/core/spaces/non_cython_bsplines/b_spline_patch_projection_non_differentiable.py +186 -0
  20. lsdo_function_spaces/core/spaces/non_cython_bsplines/b_spline_patch_projection_optimized.py +594 -0
  21. lsdo_function_spaces/core/spaces/non_cython_bsplines/b_spline_space_new.py +6 -0
  22. lsdo_function_spaces/core/spaces/non_cython_bsplines/compute_basis_matrix_jax.py +172 -0
  23. lsdo_function_spaces/core/spaces/non_cython_bsplines/compute_basis_matrix_jax_factory.py +382 -0
  24. lsdo_function_spaces/core/spaces/non_cython_bsplines/compute_basis_matrix_jax_stencil.py +451 -0
  25. lsdo_function_spaces/core/spaces/non_cython_bsplines/compute_basis_matrix_numpy.py +249 -0
  26. lsdo_function_spaces/core/spaces/non_cython_bsplines/compute_basis_matrix_numpy_factory.py +391 -0
  27. lsdo_function_spaces/core/spaces/operation_space.py +64 -0
  28. lsdo_function_spaces/core/spaces/polynomial_space.py +79 -0
  29. lsdo_function_spaces/core/spaces/rbf_space.py +136 -0
  30. lsdo_function_spaces/core/spaces/tri_space.py +256 -0
  31. lsdo_function_spaces/utils/__init__.py +0 -0
  32. lsdo_function_spaces/utils/file_io.py +484 -0
  33. lsdo_function_spaces/utils/internal_utilities.py +11 -0
  34. lsdo_function_spaces/utils/plotting_functions.py +357 -0
  35. lsdo_function_spaces/utils/utility_functions.py +148 -0
  36. lsdo_function_spaces-1.0.0.dist-info/METADATA +189 -0
  37. lsdo_function_spaces-1.0.0.dist-info/RECORD +40 -0
  38. lsdo_function_spaces-1.0.0.dist-info/WHEEL +5 -0
  39. lsdo_function_spaces-1.0.0.dist-info/licenses/LICENSE.txt +165 -0
  40. lsdo_function_spaces-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,186 @@
1
+ import jax
2
+ import jax.numpy as jnp
3
+ from lsdo_function_spaces.core.spaces.non_cython_bsplines.compute_basis_matrix_jax import evaluate_b_spline_jax
4
+
5
+ def compute_projection_residual(
6
+ point_in_space,
7
+ para_coords,
8
+ degrees,
9
+ coefficients,
10
+ knot_vectors,
11
+ ):
12
+ """
13
+ Compute the residual of the projection of a point in space onto a B-spline surface.
14
+
15
+ Parameters:
16
+ -----------
17
+ point_in_space : jnp.ndarray, shape (d,)
18
+ The point in space to project.
19
+ para_coords : jnp.ndarray, shape (M, d)
20
+ Parameter coordinates for the B-spline surface.
21
+ degrees : tuple of int
22
+ Degrees of the B-spline in each dimension.
23
+ coefficients : jnp.ndarray, shape (N, num_phys_dims)
24
+ Coefficients of the B-spline basis functions.
25
+ knot_vectors : tuple of jnp.ndarray
26
+ Knot vectors for each dimension.
27
+
28
+ Returns:
29
+ --------
30
+ residual : jnp.ndarray, shape (M,)
31
+ The residuals of the projection.
32
+ """
33
+ n_dims = len(degrees)
34
+ n_phys_dims = coefficients.shape[-1]
35
+ point_in_space = point_in_space.reshape(-1, n_phys_dims)
36
+
37
+ bsp_eval = evaluate_b_spline_jax(
38
+ us=para_coords,
39
+ degrees=degrees,
40
+ knot_vectors=knot_vectors,
41
+ coeffs=coefficients,
42
+ )
43
+
44
+ surface_jacobian = [
45
+ evaluate_b_spline_jax(
46
+ us=para_coords,
47
+ degrees=degrees,
48
+ knot_vectors=knot_vectors,
49
+ coeffs=coefficients,
50
+ der_orders=tuple(
51
+ int(i == j) for j in range(n_dims)
52
+ )
53
+ ) for i in range(n_dims)
54
+ ]
55
+ surface_jacobian_array = jnp.array(surface_jacobian).squeeze().T
56
+
57
+ diff = bsp_eval - point_in_space
58
+
59
+ residuals = [jnp.sum(diff * d, axis=1) for d in surface_jacobian] # shape: (num_pts,) for each
60
+ res = jnp.array(residuals).reshape(n_dims, )
61
+
62
+ return res, bsp_eval, surface_jacobian, surface_jacobian_array
63
+
64
+ def compute_projection_jacobian(
65
+ point_in_space,
66
+ para_coords,
67
+ degrees,
68
+ coefficients,
69
+ knot_vectors,
70
+ bsp_eval,
71
+ surface_jacobian,
72
+ ):
73
+ """
74
+ Compute the Jacobian of the projection of a point in space onto a B-spline surface.
75
+
76
+ Parameters:
77
+ -----------
78
+ point_in_space : jnp.ndarray, shape (d,)
79
+ The point in space to project.
80
+ para_coords : jnp.ndarray, shape (M, d)
81
+ Parameter coordinates for the B-spline surface.
82
+ degrees : tuple of int
83
+ Degrees of the B-spline in each dimension.
84
+ coefficients : jnp.ndarray, shape (N, num_phys_dims)
85
+ Coefficients of the B-spline basis functions.
86
+ knot_vectors : tuple of jnp.ndarray
87
+ Knot vectors for each dimension.
88
+ bsp_eval : jnp.ndarray, shape (M, num_phys_dims)
89
+ B-spline evaluation at the parameter coordinates.
90
+ surface_jacobian : list of jnp.ndarray, shape (M, num_phys_dims)
91
+ Jacobian of the B-spline surface at the parameter coordinates.
92
+
93
+ Returns:
94
+ --------
95
+ jacobian : jnp.ndarray, shape (M, d)
96
+ The Jacobian of the projection.
97
+ """
98
+ n_dims = len(degrees)
99
+
100
+ diff = (bsp_eval - point_in_space).flatten()
101
+
102
+ surface_hessian_tensor = [
103
+ [evaluate_b_spline_jax(
104
+ us=para_coords,
105
+ degrees=degrees,
106
+ knot_vectors=knot_vectors,
107
+ coeffs=coefficients,
108
+ der_orders=tuple((i == k) + (j == k) for k in range(n_dims))
109
+ ) for j in range(n_dims)
110
+ ] for i in range(n_dims)
111
+ ]
112
+
113
+ projection_jacobian = jnp.zeros((n_dims, n_dims), dtype=bsp_eval.dtype)
114
+
115
+ for i in range(n_dims):
116
+ for j in range(n_dims):
117
+ inner = jnp.sum(surface_jacobian[i] * surface_jacobian[j], axis=1) + jnp.sum(diff * surface_hessian_tensor[i][j], axis=1)
118
+ projection_jacobian = projection_jacobian.at[i, j].set(inner[0])
119
+
120
+ return projection_jacobian
121
+
122
+ def compute_point_to_bspline_projection(
123
+ point,
124
+ degrees,
125
+ coefficients,
126
+ para_coords,
127
+ knots,
128
+ max_iter=100,
129
+ tol=1e-12,
130
+ ):
131
+ """Project a point onto an n-dimensional B-spline using Newton iteration."""
132
+ n_dims = len(degrees) # parametric dimensions
133
+
134
+ para_coords = para_coords.reshape(n_dims, )
135
+
136
+ # knots = tuple([knots[i] for i in range(n_dims)])
137
+
138
+ def body(state):
139
+ i, para_coords, _, _, _, _, _ = state
140
+
141
+ res, bsp_eval, surface_jacobian, surface_jacobian_array = compute_projection_residual(
142
+ point, para_coords, degrees, coefficients, knots
143
+ )
144
+ J = compute_projection_jacobian(
145
+ point, para_coords, degrees, coefficients, knots, bsp_eval, surface_jacobian,
146
+ )
147
+
148
+ grad = res
149
+ # Applying active-set like approach
150
+ # Inactive directions are those where the gradient is zero or the parameter is at the boundary
151
+ inactive_mask = jnp.logical_or(
152
+ jnp.logical_and(para_coords <= 0.0, grad > 0.0),
153
+ jnp.logical_and(para_coords >= 1.0, grad < 0.0),
154
+ )
155
+ inactive_mask = jnp.logical_or(inactive_mask, grad == 0.0)
156
+ active_mask = ~inactive_mask
157
+
158
+ # Mask Jacobian and residual using active_mask
159
+ J_masked = J * (active_mask[:, None] & active_mask[None, :])
160
+ res_masked = res * active_mask
161
+
162
+ res_norm = jnp.linalg.norm(res_masked)
163
+
164
+ # NOTE: we are solving an augmented system (always 2x2)
165
+ # Ideally we would remove the inactive directions from the system
166
+ # However, for JAX, the dimensions must be fixed for jit compilation
167
+ step = -jnp.linalg.solve(J_masked + jnp.eye(n_dims) * (~active_mask), res_masked)
168
+ step = step * active_mask # zero out inactive directions
169
+
170
+ para_coords_new = jnp.clip(para_coords + step, 0.0, 1.0)
171
+ converged_new = res_norm < tol
172
+
173
+ return (i + 1, para_coords_new, res_masked, converged_new, J, active_mask, surface_jacobian_array)
174
+
175
+ def cond(state):
176
+ i, _, _, converged, _, _, _ = state
177
+ return (i < max_iter) & (~converged)
178
+
179
+ dim = len(degrees)
180
+ bool_init = jnp.zeros_like(para_coords, dtype=jnp.bool_)
181
+ dS_dxi_init = jnp.zeros((3, dim))
182
+ init_state = (0, para_coords, jnp.zeros_like(para_coords), False, jnp.zeros((dim, dim)), bool_init, dS_dxi_init)
183
+ final_i, final_coords, final_res, final_converged, J, mask, surface_jacobian = jax.lax.while_loop(cond, body, init_state)
184
+
185
+ return final_coords, final_res, final_converged, final_i, J, mask, surface_jacobian
186
+