warp-lang 1.2.2__py3-none-win_amd64.whl → 1.3.0__py3-none-win_amd64.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.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +8 -6
- warp/autograd.py +823 -0
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +6 -2
- warp/builtins.py +1410 -886
- warp/codegen.py +503 -166
- warp/config.py +48 -18
- warp/context.py +400 -198
- warp/dlpack.py +8 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +1 -1
- warp/examples/benchmarks/benchmark_interop_torch.py +158 -0
- warp/examples/benchmarks/benchmark_launches.py +1 -1
- warp/examples/core/example_cupy.py +78 -0
- warp/examples/fem/example_apic_fluid.py +17 -36
- warp/examples/fem/example_burgers.py +9 -18
- warp/examples/fem/example_convection_diffusion.py +7 -17
- warp/examples/fem/example_convection_diffusion_dg.py +27 -47
- warp/examples/fem/example_deformed_geometry.py +11 -22
- warp/examples/fem/example_diffusion.py +7 -18
- warp/examples/fem/example_diffusion_3d.py +24 -28
- warp/examples/fem/example_diffusion_mgpu.py +7 -14
- warp/examples/fem/example_magnetostatics.py +190 -0
- warp/examples/fem/example_mixed_elasticity.py +111 -80
- warp/examples/fem/example_navier_stokes.py +30 -34
- warp/examples/fem/example_nonconforming_contact.py +290 -0
- warp/examples/fem/example_stokes.py +17 -32
- warp/examples/fem/example_stokes_transfer.py +12 -21
- warp/examples/fem/example_streamlines.py +350 -0
- warp/examples/fem/utils.py +936 -0
- warp/fabric.py +5 -2
- warp/fem/__init__.py +13 -3
- warp/fem/cache.py +161 -11
- warp/fem/dirichlet.py +37 -28
- warp/fem/domain.py +105 -14
- warp/fem/field/__init__.py +14 -3
- warp/fem/field/field.py +454 -11
- warp/fem/field/nodal_field.py +33 -18
- warp/fem/geometry/deformed_geometry.py +50 -15
- warp/fem/geometry/hexmesh.py +12 -24
- warp/fem/geometry/nanogrid.py +106 -31
- warp/fem/geometry/quadmesh_2d.py +6 -11
- warp/fem/geometry/tetmesh.py +103 -61
- warp/fem/geometry/trimesh_2d.py +98 -47
- warp/fem/integrate.py +231 -186
- warp/fem/operator.py +14 -9
- warp/fem/quadrature/pic_quadrature.py +35 -9
- warp/fem/quadrature/quadrature.py +119 -32
- warp/fem/space/basis_space.py +98 -22
- warp/fem/space/collocated_function_space.py +3 -1
- warp/fem/space/function_space.py +7 -2
- warp/fem/space/grid_2d_function_space.py +3 -3
- warp/fem/space/grid_3d_function_space.py +4 -4
- warp/fem/space/hexmesh_function_space.py +3 -2
- warp/fem/space/nanogrid_function_space.py +12 -14
- warp/fem/space/partition.py +45 -47
- warp/fem/space/restriction.py +19 -16
- warp/fem/space/shape/cube_shape_function.py +91 -3
- warp/fem/space/shape/shape_function.py +7 -0
- warp/fem/space/shape/square_shape_function.py +32 -0
- warp/fem/space/shape/tet_shape_function.py +11 -7
- warp/fem/space/shape/triangle_shape_function.py +10 -1
- warp/fem/space/topology.py +116 -42
- warp/fem/types.py +8 -1
- warp/fem/utils.py +301 -83
- warp/native/array.h +16 -0
- warp/native/builtin.h +0 -15
- warp/native/cuda_util.cpp +14 -6
- warp/native/exports.h +1348 -1308
- warp/native/quat.h +79 -0
- warp/native/rand.h +27 -4
- warp/native/sparse.cpp +83 -81
- warp/native/sparse.cu +381 -453
- warp/native/vec.h +64 -0
- warp/native/volume.cpp +40 -49
- warp/native/volume_builder.cu +2 -3
- warp/native/volume_builder.h +12 -17
- warp/native/warp.cu +3 -3
- warp/native/warp.h +69 -59
- warp/render/render_opengl.py +17 -9
- warp/sim/articulation.py +117 -17
- warp/sim/collide.py +35 -29
- warp/sim/model.py +123 -18
- warp/sim/render.py +3 -1
- warp/sparse.py +867 -203
- warp/stubs.py +312 -541
- warp/tape.py +29 -1
- warp/tests/disabled_kinematics.py +1 -1
- warp/tests/test_adam.py +1 -1
- warp/tests/test_arithmetic.py +1 -1
- warp/tests/test_array.py +58 -1
- warp/tests/test_array_reduce.py +1 -1
- warp/tests/test_async.py +1 -1
- warp/tests/test_atomic.py +1 -1
- warp/tests/test_bool.py +1 -1
- warp/tests/test_builtins_resolution.py +1 -1
- warp/tests/test_bvh.py +6 -1
- warp/tests/test_closest_point_edge_edge.py +1 -1
- warp/tests/test_codegen.py +66 -1
- warp/tests/test_compile_consts.py +1 -1
- warp/tests/test_conditional.py +1 -1
- warp/tests/test_copy.py +1 -1
- warp/tests/test_ctypes.py +1 -1
- warp/tests/test_dense.py +1 -1
- warp/tests/test_devices.py +1 -1
- warp/tests/test_dlpack.py +1 -1
- warp/tests/test_examples.py +33 -4
- warp/tests/test_fabricarray.py +5 -2
- warp/tests/test_fast_math.py +1 -1
- warp/tests/test_fem.py +213 -6
- warp/tests/test_fp16.py +1 -1
- warp/tests/test_func.py +1 -1
- warp/tests/test_future_annotations.py +90 -0
- warp/tests/test_generics.py +1 -1
- warp/tests/test_grad.py +1 -1
- warp/tests/test_grad_customs.py +1 -1
- warp/tests/test_grad_debug.py +247 -0
- warp/tests/test_hash_grid.py +6 -1
- warp/tests/test_implicit_init.py +354 -0
- warp/tests/test_import.py +1 -1
- warp/tests/test_indexedarray.py +1 -1
- warp/tests/test_intersect.py +1 -1
- warp/tests/test_jax.py +1 -1
- warp/tests/test_large.py +1 -1
- warp/tests/test_launch.py +1 -1
- warp/tests/test_lerp.py +1 -1
- warp/tests/test_linear_solvers.py +1 -1
- warp/tests/test_lvalue.py +1 -1
- warp/tests/test_marching_cubes.py +5 -2
- warp/tests/test_mat.py +34 -35
- warp/tests/test_mat_lite.py +2 -1
- warp/tests/test_mat_scalar_ops.py +1 -1
- warp/tests/test_math.py +1 -1
- warp/tests/test_matmul.py +20 -16
- warp/tests/test_matmul_lite.py +1 -1
- warp/tests/test_mempool.py +1 -1
- warp/tests/test_mesh.py +5 -2
- warp/tests/test_mesh_query_aabb.py +1 -1
- warp/tests/test_mesh_query_point.py +1 -1
- warp/tests/test_mesh_query_ray.py +1 -1
- warp/tests/test_mlp.py +1 -1
- warp/tests/test_model.py +1 -1
- warp/tests/test_module_hashing.py +77 -1
- warp/tests/test_modules_lite.py +1 -1
- warp/tests/test_multigpu.py +1 -1
- warp/tests/test_noise.py +1 -1
- warp/tests/test_operators.py +1 -1
- warp/tests/test_options.py +1 -1
- warp/tests/test_overwrite.py +542 -0
- warp/tests/test_peer.py +1 -1
- warp/tests/test_pinned.py +1 -1
- warp/tests/test_print.py +1 -1
- warp/tests/test_quat.py +15 -1
- warp/tests/test_rand.py +1 -1
- warp/tests/test_reload.py +1 -1
- warp/tests/test_rounding.py +1 -1
- warp/tests/test_runlength_encode.py +1 -1
- warp/tests/test_scalar_ops.py +95 -0
- warp/tests/test_sim_grad.py +1 -1
- warp/tests/test_sim_kinematics.py +1 -1
- warp/tests/test_smoothstep.py +1 -1
- warp/tests/test_sparse.py +82 -15
- warp/tests/test_spatial.py +1 -1
- warp/tests/test_special_values.py +2 -11
- warp/tests/test_streams.py +11 -1
- warp/tests/test_struct.py +1 -1
- warp/tests/test_tape.py +1 -1
- warp/tests/test_torch.py +194 -1
- warp/tests/test_transient_module.py +1 -1
- warp/tests/test_types.py +1 -1
- warp/tests/test_utils.py +1 -1
- warp/tests/test_vec.py +15 -63
- warp/tests/test_vec_lite.py +2 -1
- warp/tests/test_vec_scalar_ops.py +65 -1
- warp/tests/test_verify_fp.py +1 -1
- warp/tests/test_volume.py +28 -2
- warp/tests/test_volume_write.py +1 -1
- warp/tests/unittest_serial.py +1 -1
- warp/tests/unittest_suites.py +9 -1
- warp/tests/walkthrough_debug.py +1 -1
- warp/thirdparty/unittest_parallel.py +2 -5
- warp/torch.py +103 -41
- warp/types.py +341 -224
- warp/utils.py +11 -2
- {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/METADATA +99 -46
- warp_lang-1.3.0.dist-info/RECORD +368 -0
- warp/examples/fem/bsr_utils.py +0 -378
- warp/examples/fem/mesh_utils.py +0 -133
- warp/examples/fem/plot_utils.py +0 -292
- warp_lang-1.2.2.dist-info/RECORD +0 -359
- {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/top_level.txt +0 -0
|
@@ -8,77 +8,101 @@
|
|
|
8
8
|
###########################################################################
|
|
9
9
|
# Example Mixed Elasticity
|
|
10
10
|
#
|
|
11
|
-
# This example illustrates using Mixed FEM to solve a
|
|
12
|
-
# 2D linear elasticity problem:
|
|
11
|
+
# This example illustrates using Mixed FEM to solve a nonlinear static elasticity equilibrium problem:
|
|
13
12
|
#
|
|
14
|
-
# Div[
|
|
13
|
+
# Div[ d/dF Psi(F(u)) ] = 0
|
|
15
14
|
#
|
|
16
|
-
# with Dirichlet boundary conditions on
|
|
17
|
-
# and
|
|
15
|
+
# with Dirichlet boundary conditions on vertical sides,
|
|
16
|
+
# and Psi an elastic potential function of the deformation gradient (here Neo-Hookean)
|
|
17
|
+
#
|
|
18
|
+
# which we write as a sequence of Newton iterations:
|
|
19
|
+
# int {sigma : grad v} = 0 for all displacement test functions v
|
|
20
|
+
# int {sigma : tau} = int{dPsi/dF : tau} + int{grad du : d2 Psi/dF2 : tau} for all stress test functions tau
|
|
18
21
|
###########################################################################
|
|
19
22
|
|
|
20
23
|
import numpy as np
|
|
21
24
|
|
|
22
25
|
import warp as wp
|
|
26
|
+
import warp.examples.fem.utils as fem_example_utils
|
|
23
27
|
import warp.fem as fem
|
|
24
|
-
from warp.sparse import bsr_mm, bsr_transposed
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
from .bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
|
|
28
|
-
from .mesh_utils import gen_quadmesh, gen_trimesh
|
|
29
|
-
from .plot_utils import Plot
|
|
30
|
-
except ImportError:
|
|
31
|
-
from bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
|
|
32
|
-
from mesh_utils import gen_quadmesh, gen_trimesh
|
|
33
|
-
from plot_utils import Plot
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@wp.func
|
|
37
|
-
def compute_stress(tau: wp.mat22, E: wp.mat33):
|
|
38
|
-
"""Strain to stress computation"""
|
|
39
|
-
tau_sym = wp.vec3(tau[0, 0], tau[1, 1], tau[0, 1] + tau[1, 0])
|
|
40
|
-
sig_sym = E * tau_sym
|
|
41
|
-
return wp.mat22(sig_sym[0], 0.5 * sig_sym[2], 0.5 * sig_sym[2], sig_sym[1])
|
|
42
28
|
|
|
43
29
|
|
|
44
30
|
@fem.integrand
|
|
45
|
-
def
|
|
31
|
+
def displacement_gradient_form(
|
|
46
32
|
s: fem.Sample,
|
|
47
33
|
u: fem.Field,
|
|
48
34
|
tau: fem.Field,
|
|
49
35
|
):
|
|
50
|
-
"""
|
|
51
|
-
return wp.ddot(tau(s), fem.
|
|
36
|
+
"""grad(u) : tau"""
|
|
37
|
+
return wp.ddot(tau(s), fem.grad(u, s))
|
|
52
38
|
|
|
53
39
|
|
|
54
40
|
@fem.integrand
|
|
55
|
-
def
|
|
56
|
-
"""
|
|
57
|
-
|
|
41
|
+
def nh_stress_form(s: fem.Sample, tau: fem.Field, u_cur: fem.Field, lame: wp.vec2):
|
|
42
|
+
"""d Psi/dF : tau"""
|
|
43
|
+
|
|
44
|
+
F = wp.identity(n=2, dtype=float) + fem.grad(u_cur, s)
|
|
45
|
+
|
|
46
|
+
J = wp.determinant(F)
|
|
47
|
+
mu_nh = 2.0 * lame[1]
|
|
48
|
+
lambda_nh = lame[0] + lame[1]
|
|
49
|
+
gamma = 1.0 + mu_nh / lambda_nh
|
|
50
|
+
|
|
51
|
+
dJ_dS = wp.mat22(F[1, 1], -F[1, 0], -F[0, 1], F[0, 0])
|
|
52
|
+
nh_stress = mu_nh * F + lambda_nh * (J - gamma) * dJ_dS
|
|
53
|
+
|
|
54
|
+
return wp.ddot(tau(s), nh_stress)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@fem.integrand
|
|
58
|
+
def nh_stress_delta_form(s: fem.Sample, tau: fem.Field, u: fem.Field, u_cur: fem.Field, lame: wp.vec2):
|
|
59
|
+
"""grad(u) : d2 Psi/dF2 : tau"""
|
|
60
|
+
|
|
61
|
+
tau_s = tau(s)
|
|
62
|
+
sigma_s = fem.grad(u, s)
|
|
63
|
+
|
|
64
|
+
F = wp.identity(n=2, dtype=float) + fem.grad(u_cur, s)
|
|
65
|
+
|
|
66
|
+
dJ_dF = wp.mat22(F[1, 1], -F[1, 0], -F[0, 1], F[0, 0])
|
|
67
|
+
|
|
68
|
+
mu_nh = 2.0 * lame[1]
|
|
69
|
+
lambda_nh = lame[0] + lame[1]
|
|
70
|
+
|
|
71
|
+
dpsi_dpsi = mu_nh * wp.ddot(tau_s, sigma_s) + lambda_nh * wp.ddot(dJ_dF * tau_s, dJ_dF * sigma_s)
|
|
72
|
+
|
|
73
|
+
# positive part of d2J_dS2
|
|
74
|
+
gamma = 1.0 + mu_nh / lambda_nh
|
|
75
|
+
J = wp.determinant(F)
|
|
76
|
+
if J >= gamma:
|
|
77
|
+
d2J_dF_sig = wp.mat22(sigma_s[1, 1], 0.0, 0.0, sigma_s[0, 0])
|
|
78
|
+
else:
|
|
79
|
+
d2J_dF_sig = wp.mat22(0.0, -sigma_s[1, 0], -sigma_s[0, 1], 0.0)
|
|
80
|
+
|
|
81
|
+
return dpsi_dpsi + lambda_nh * (J - gamma) * wp.ddot(d2J_dF_sig, tau_s)
|
|
58
82
|
|
|
59
83
|
|
|
60
84
|
@fem.integrand
|
|
61
|
-
def
|
|
85
|
+
def vertical_boundary_projector_form(
|
|
62
86
|
s: fem.Sample,
|
|
63
87
|
domain: fem.Domain,
|
|
64
88
|
u: fem.Field,
|
|
65
89
|
v: fem.Field,
|
|
66
90
|
):
|
|
67
|
-
# non zero on
|
|
91
|
+
# non zero on vertical boundary of domain only
|
|
68
92
|
nor = fem.normal(domain, s)
|
|
69
|
-
return wp.dot(u(s), v(s)) * wp.abs(nor[
|
|
93
|
+
return wp.dot(u(s), v(s)) * wp.abs(nor[0])
|
|
70
94
|
|
|
71
95
|
|
|
72
96
|
@fem.integrand
|
|
73
|
-
def
|
|
97
|
+
def vertical_displacement_form(
|
|
74
98
|
s: fem.Sample,
|
|
75
99
|
domain: fem.Domain,
|
|
76
100
|
v: fem.Field,
|
|
77
101
|
displacement: float,
|
|
78
102
|
):
|
|
79
|
-
# opposed to normal on
|
|
103
|
+
# opposed to normal on vertical boundary of domain only
|
|
80
104
|
nor = fem.normal(domain, s)
|
|
81
|
-
return -wp.abs(nor[
|
|
105
|
+
return -wp.abs(nor[0]) * displacement * wp.dot(nor, v(s))
|
|
82
106
|
|
|
83
107
|
|
|
84
108
|
@fem.integrand
|
|
@@ -98,7 +122,6 @@ class Example:
|
|
|
98
122
|
resolution=25,
|
|
99
123
|
mesh="grid",
|
|
100
124
|
displacement=0.1,
|
|
101
|
-
young_modulus=1.0,
|
|
102
125
|
poisson_ratio=0.5,
|
|
103
126
|
nonconforming_stresses=False,
|
|
104
127
|
):
|
|
@@ -106,49 +129,45 @@ class Example:
|
|
|
106
129
|
|
|
107
130
|
self._displacement = displacement
|
|
108
131
|
|
|
109
|
-
# Grid or
|
|
132
|
+
# Grid or mesh geometry
|
|
110
133
|
if mesh == "tri":
|
|
111
|
-
positions, tri_vidx = gen_trimesh(res=wp.vec2i(resolution))
|
|
134
|
+
positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(resolution))
|
|
112
135
|
self._geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
113
136
|
elif mesh == "quad":
|
|
114
|
-
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(resolution))
|
|
137
|
+
positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
|
|
115
138
|
self._geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
116
139
|
else:
|
|
117
140
|
self._geo = fem.Grid2D(res=wp.vec2i(resolution))
|
|
118
141
|
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
poisson = poisson_ratio
|
|
122
|
-
self._elasticity_mat = wp.mat33(
|
|
123
|
-
young
|
|
124
|
-
/ (1.0 - poisson * poisson)
|
|
125
|
-
* np.array(
|
|
126
|
-
[
|
|
127
|
-
[1.0, poisson, 0.0],
|
|
128
|
-
[poisson, 1.0, 0.0],
|
|
129
|
-
[0.0, 0.0, (2.0 * (1.0 + poisson)) * (1.0 - poisson * poisson)],
|
|
130
|
-
]
|
|
131
|
-
)
|
|
132
|
-
)
|
|
142
|
+
# Lame coefficients from Young modulus and Poisson ratio
|
|
143
|
+
self._lame = wp.vec2(1.0 / (1.0 + poisson_ratio) * np.array([poisson_ratio / (1.0 - poisson_ratio), 0.5]))
|
|
133
144
|
|
|
134
|
-
# Function spaces -- S_k for displacement,
|
|
145
|
+
# Function spaces -- S_k for displacement, Q_k or P_{k-1}d for stress
|
|
135
146
|
self._u_space = fem.make_polynomial_space(
|
|
136
147
|
self._geo, degree=degree, dtype=wp.vec2, element_basis=fem.ElementBasis.SERENDIPITY
|
|
137
148
|
)
|
|
138
149
|
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
if isinstance(self._geo.reference_cell(), fem.geometry.element.Triangle):
|
|
151
|
+
# triangle elements
|
|
152
|
+
tau_basis = fem.ElementBasis.NONCONFORMING_POLYNOMIAL
|
|
153
|
+
tau_degree = degree - 1
|
|
154
|
+
else:
|
|
155
|
+
# square elements
|
|
156
|
+
tau_basis = fem.ElementBasis.LAGRANGE
|
|
157
|
+
tau_degree = degree
|
|
158
|
+
|
|
141
159
|
self._tau_space = fem.make_polynomial_space(
|
|
142
160
|
self._geo,
|
|
143
|
-
degree=
|
|
161
|
+
degree=tau_degree,
|
|
144
162
|
discontinuous=True,
|
|
145
163
|
element_basis=tau_basis,
|
|
146
|
-
|
|
164
|
+
family=fem.Polynomial.GAUSS_LEGENDRE,
|
|
165
|
+
dtype=wp.mat22,
|
|
147
166
|
)
|
|
148
167
|
|
|
149
168
|
self._u_field = self._u_space.make_field()
|
|
150
169
|
|
|
151
|
-
self.renderer = Plot()
|
|
170
|
+
self.renderer = fem_example_utils.Plot()
|
|
152
171
|
|
|
153
172
|
def step(self):
|
|
154
173
|
boundary = fem.BoundarySides(self._geo)
|
|
@@ -158,14 +177,14 @@ class Example:
|
|
|
158
177
|
u_bd_test = fem.make_test(space=self._u_space, domain=boundary)
|
|
159
178
|
u_bd_trial = fem.make_trial(space=self._u_space, domain=boundary)
|
|
160
179
|
u_bd_rhs = fem.integrate(
|
|
161
|
-
|
|
180
|
+
vertical_displacement_form,
|
|
162
181
|
fields={"v": u_bd_test},
|
|
163
182
|
values={"displacement": self._displacement},
|
|
164
183
|
nodal=True,
|
|
165
184
|
output_dtype=wp.vec2d,
|
|
166
185
|
)
|
|
167
186
|
u_bd_matrix = fem.integrate(
|
|
168
|
-
|
|
187
|
+
vertical_boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True
|
|
169
188
|
)
|
|
170
189
|
|
|
171
190
|
# Stress/velocity coupling
|
|
@@ -173,30 +192,44 @@ class Example:
|
|
|
173
192
|
tau_test = fem.make_test(space=self._tau_space, domain=domain)
|
|
174
193
|
tau_trial = fem.make_trial(space=self._tau_space, domain=domain)
|
|
175
194
|
|
|
176
|
-
|
|
177
|
-
stress_matrix = fem.integrate(
|
|
178
|
-
stress_form, fields={"u": u_trial, "tau": tau_test}, values={"E": self._elasticity_mat}
|
|
179
|
-
)
|
|
195
|
+
gradient_matrix = fem.integrate(displacement_gradient_form, fields={"u": u_trial, "tau": tau_test}).transpose()
|
|
180
196
|
|
|
181
197
|
# Compute inverse of the (block-diagonal) tau mass matrix
|
|
182
198
|
tau_inv_mass_matrix = fem.integrate(tensor_mass_form, fields={"sig": tau_trial, "tau": tau_test}, nodal=True)
|
|
183
|
-
|
|
199
|
+
fem_example_utils.invert_diagonal_bsr_matrix(tau_inv_mass_matrix)
|
|
200
|
+
|
|
201
|
+
# Newton iterations (without line-search for simplicity)
|
|
202
|
+
for newton_iteration in range(5):
|
|
203
|
+
stress_matrix = fem.integrate(
|
|
204
|
+
nh_stress_delta_form,
|
|
205
|
+
fields={"u_cur": self._u_field, "u": u_trial, "tau": tau_test},
|
|
206
|
+
values={"lame": self._lame},
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
stress_rhs = fem.integrate(
|
|
210
|
+
nh_stress_form,
|
|
211
|
+
fields={"u_cur": self._u_field, "tau": tau_test},
|
|
212
|
+
values={"lame": self._lame},
|
|
213
|
+
output_dtype=wp.vec(length=stress_matrix.block_shape[0], dtype=wp.float64),
|
|
214
|
+
)
|
|
184
215
|
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
# Assemble system matrix
|
|
217
|
+
u_matrix = gradient_matrix @ tau_inv_mass_matrix @ stress_matrix
|
|
187
218
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
219
|
+
# Enforce boundary conditions (apply displacement only at first iteration)
|
|
220
|
+
u_rhs = -gradient_matrix @ (tau_inv_mass_matrix @ stress_rhs)
|
|
221
|
+
fem.project_linear_system(u_matrix, u_rhs, u_bd_matrix, u_bd_rhs if newton_iteration == 0 else None)
|
|
191
222
|
|
|
192
|
-
|
|
193
|
-
|
|
223
|
+
x = wp.zeros_like(u_rhs)
|
|
224
|
+
fem_example_utils.bsr_cg(u_matrix, b=u_rhs, x=x, quiet=self._quiet)
|
|
194
225
|
|
|
195
|
-
|
|
196
|
-
|
|
226
|
+
# Extract result -- cast to float32 and accumulate to displacement field
|
|
227
|
+
delta_u = wp.empty_like(self._u_field.dof_values)
|
|
228
|
+
wp.utils.array_cast(in_array=x, out_array=delta_u)
|
|
229
|
+
fem.utils.array_axpy(x=delta_u, y=self._u_field.dof_values)
|
|
197
230
|
|
|
198
231
|
def render(self):
|
|
199
|
-
self.renderer.
|
|
232
|
+
self.renderer.add_field("solution", self._u_field)
|
|
200
233
|
|
|
201
234
|
|
|
202
235
|
if __name__ == "__main__":
|
|
@@ -208,8 +241,7 @@ if __name__ == "__main__":
|
|
|
208
241
|
parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
|
|
209
242
|
parser.add_argument("--resolution", type=int, default=25, help="Grid resolution.")
|
|
210
243
|
parser.add_argument("--degree", type=int, default=2, help="Polynomial degree of shape functions.")
|
|
211
|
-
parser.add_argument("--displacement", type=float, default
|
|
212
|
-
parser.add_argument("--young_modulus", type=float, default=1.0)
|
|
244
|
+
parser.add_argument("--displacement", type=float, default=-0.5)
|
|
213
245
|
parser.add_argument("--poisson_ratio", type=float, default=0.5)
|
|
214
246
|
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
215
247
|
parser.add_argument(
|
|
@@ -231,7 +263,6 @@ if __name__ == "__main__":
|
|
|
231
263
|
resolution=args.resolution,
|
|
232
264
|
mesh=args.mesh,
|
|
233
265
|
displacement=args.displacement,
|
|
234
|
-
young_modulus=args.young_modulus,
|
|
235
266
|
poisson_ratio=args.poisson_ratio,
|
|
236
267
|
nonconforming_stresses=args.nonconforming_stresses,
|
|
237
268
|
)
|
|
@@ -239,4 +270,4 @@ if __name__ == "__main__":
|
|
|
239
270
|
example.render()
|
|
240
271
|
|
|
241
272
|
if not args.headless:
|
|
242
|
-
example.renderer.plot()
|
|
273
|
+
example.renderer.plot(options={"solution": {"displacement": {}}})
|
|
@@ -18,27 +18,18 @@
|
|
|
18
18
|
###########################################################################
|
|
19
19
|
|
|
20
20
|
import warp as wp
|
|
21
|
+
import warp.examples.fem.utils as fem_example_utils
|
|
21
22
|
import warp.fem as fem
|
|
22
23
|
from warp.fem.utils import array_axpy
|
|
23
|
-
from warp.sparse import bsr_copy, bsr_mm, bsr_mv
|
|
24
24
|
|
|
25
|
-
try:
|
|
26
|
-
from .bsr_utils import SaddleSystem, bsr_solve_saddle
|
|
27
|
-
from .mesh_utils import gen_trimesh
|
|
28
|
-
from .plot_utils import Plot
|
|
29
|
-
except ImportError:
|
|
30
|
-
from bsr_utils import SaddleSystem, bsr_solve_saddle
|
|
31
|
-
from mesh_utils import gen_trimesh
|
|
32
|
-
from plot_utils import Plot
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def u_boundary_value(s: fem.Sample, domain: fem.Domain, v: fem.Field, top_vel: float):
|
|
26
|
+
@wp.func
|
|
27
|
+
def u_boundary_value(x: wp.vec2, box_height: float, top_velocity: float):
|
|
37
28
|
# Horizontal velocity on top of domain, zero elsewhere
|
|
38
|
-
if
|
|
39
|
-
return wp.
|
|
29
|
+
if x[1] >= box_height:
|
|
30
|
+
return wp.vec2(top_velocity, 0.0)
|
|
40
31
|
|
|
41
|
-
return wp.
|
|
32
|
+
return wp.vec2(0.0, 0.0)
|
|
42
33
|
|
|
43
34
|
|
|
44
35
|
@fem.integrand
|
|
@@ -100,8 +91,8 @@ class Example:
|
|
|
100
91
|
viscosity = top_velocity / Re
|
|
101
92
|
|
|
102
93
|
if tri_mesh:
|
|
103
|
-
positions, tri_vidx = gen_trimesh(res=wp.vec2i(res))
|
|
104
|
-
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
94
|
+
positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(res))
|
|
95
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions, build_bvh=True)
|
|
105
96
|
else:
|
|
106
97
|
geo = fem.Grid2D(res=wp.vec2i(res))
|
|
107
98
|
|
|
@@ -132,10 +123,14 @@ class Example:
|
|
|
132
123
|
u_bd_test = fem.make_test(space=u_space, domain=boundary)
|
|
133
124
|
u_bd_trial = fem.make_trial(space=u_space, domain=boundary)
|
|
134
125
|
u_bd_projector = fem.integrate(mass_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True)
|
|
126
|
+
|
|
127
|
+
# Define an implicit field for our boundary condition value and integrate
|
|
128
|
+
u_bd_field = fem.ImplicitField(
|
|
129
|
+
domain=boundary, func=u_boundary_value, values={"top_velocity": top_velocity, "box_height": 1.0}
|
|
130
|
+
)
|
|
135
131
|
u_bd_value = fem.integrate(
|
|
136
|
-
|
|
137
|
-
fields={"v": u_bd_test},
|
|
138
|
-
values={"top_vel": top_velocity},
|
|
132
|
+
mass_form,
|
|
133
|
+
fields={"u": u_bd_field, "v": u_bd_test},
|
|
139
134
|
nodal=True,
|
|
140
135
|
output_dtype=wp.vec2d,
|
|
141
136
|
)
|
|
@@ -145,15 +140,11 @@ class Example:
|
|
|
145
140
|
u_bd_rhs = wp.zeros_like(u_bd_value)
|
|
146
141
|
fem.project_linear_system(u_matrix, u_bd_rhs, u_bd_projector, u_bd_value, normalize_projector=False)
|
|
147
142
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
bsr_mv(div_matrix, u_bd_value, y=div_bd_rhs, alpha=-1.0)
|
|
151
|
-
|
|
152
|
-
# div_matrix = div_matrix - div_matrix * bd_projector
|
|
153
|
-
bsr_mm(x=bsr_copy(div_matrix), y=u_bd_projector, z=div_matrix, alpha=-1.0, beta=1.0)
|
|
143
|
+
div_bd_rhs = -div_matrix @ u_bd_value
|
|
144
|
+
div_matrix -= div_matrix @ u_bd_projector
|
|
154
145
|
|
|
155
146
|
# Assemble saddle system
|
|
156
|
-
self._saddle_system = SaddleSystem(u_matrix, div_matrix)
|
|
147
|
+
self._saddle_system = fem_example_utils.SaddleSystem(u_matrix, div_matrix)
|
|
157
148
|
|
|
158
149
|
# Save data for computing time steps rhs
|
|
159
150
|
self._u_bd_projector = u_bd_projector
|
|
@@ -165,8 +156,8 @@ class Example:
|
|
|
165
156
|
self._u_field = u_space.make_field()
|
|
166
157
|
self._p_field = p_space.make_field()
|
|
167
158
|
|
|
168
|
-
self.renderer = Plot()
|
|
169
|
-
self.renderer.
|
|
159
|
+
self.renderer = fem_example_utils.Plot()
|
|
160
|
+
self.renderer.add_field("velocity", self._u_field)
|
|
170
161
|
|
|
171
162
|
def step(self):
|
|
172
163
|
self.current_frame += 1
|
|
@@ -180,7 +171,7 @@ class Example:
|
|
|
180
171
|
|
|
181
172
|
# Apply boundary conditions
|
|
182
173
|
# u_rhs = (I - P) * u_rhs + u_bd_rhs
|
|
183
|
-
bsr_mv(self._u_bd_projector, x=u_rhs, y=u_rhs, alpha=-1.0, beta=1.0)
|
|
174
|
+
wp.sparse.bsr_mv(self._u_bd_projector, x=u_rhs, y=u_rhs, alpha=-1.0, beta=1.0)
|
|
184
175
|
array_axpy(x=self._u_bd_rhs, y=u_rhs, alpha=1.0, beta=1.0)
|
|
185
176
|
|
|
186
177
|
p_rhs = self._div_bd_rhs
|
|
@@ -190,7 +181,7 @@ class Example:
|
|
|
190
181
|
wp.utils.array_cast(out_array=x_u, in_array=self._u_field.dof_values)
|
|
191
182
|
wp.utils.array_cast(out_array=x_p, in_array=self._p_field.dof_values)
|
|
192
183
|
|
|
193
|
-
bsr_solve_saddle(
|
|
184
|
+
fem_example_utils.bsr_solve_saddle(
|
|
194
185
|
saddle_system=self._saddle_system,
|
|
195
186
|
tol=1.0e-6,
|
|
196
187
|
x_u=x_u,
|
|
@@ -205,7 +196,7 @@ class Example:
|
|
|
205
196
|
|
|
206
197
|
def render(self):
|
|
207
198
|
self.renderer.begin_frame(time=self.current_frame * self.sim_dt)
|
|
208
|
-
self.renderer.
|
|
199
|
+
self.renderer.add_field("velocity", self._u_field)
|
|
209
200
|
self.renderer.end_frame()
|
|
210
201
|
|
|
211
202
|
|
|
@@ -251,7 +242,12 @@ if __name__ == "__main__":
|
|
|
251
242
|
example.step()
|
|
252
243
|
example.render()
|
|
253
244
|
|
|
254
|
-
example.renderer.
|
|
245
|
+
example.renderer.add_field("velocity_final", example._u_field)
|
|
255
246
|
|
|
256
247
|
if not args.headless:
|
|
257
|
-
example.renderer.plot(
|
|
248
|
+
example.renderer.plot(
|
|
249
|
+
options={
|
|
250
|
+
"velocity": {"arrows": {"glyph_scale": 0.25}},
|
|
251
|
+
"velocity_final": {"streamlines": {"density": 2.0}},
|
|
252
|
+
}
|
|
253
|
+
)
|