warp-lang 1.1.0__py3-none-macosx_10_13_universal2.whl → 1.2.0__py3-none-macosx_10_13_universal2.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/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +10 -37
- warp/build_dll.py +2 -2
- warp/builtins.py +274 -6
- warp/codegen.py +51 -4
- warp/config.py +2 -2
- warp/constants.py +4 -0
- warp/context.py +418 -203
- warp/examples/benchmarks/benchmark_api.py +0 -2
- warp/examples/benchmarks/benchmark_cloth_warp.py +0 -1
- warp/examples/benchmarks/benchmark_launches.py +0 -2
- warp/examples/core/example_dem.py +0 -2
- warp/examples/core/example_fluid.py +0 -2
- warp/examples/core/example_graph_capture.py +0 -2
- warp/examples/core/example_marching_cubes.py +0 -2
- warp/examples/core/example_mesh.py +0 -2
- warp/examples/core/example_mesh_intersect.py +0 -2
- warp/examples/core/example_nvdb.py +0 -2
- warp/examples/core/example_raycast.py +0 -2
- warp/examples/core/example_raymarch.py +0 -2
- warp/examples/core/example_render_opengl.py +0 -2
- warp/examples/core/example_sph.py +0 -2
- warp/examples/core/example_torch.py +0 -3
- warp/examples/core/example_wave.py +0 -2
- warp/examples/fem/example_apic_fluid.py +140 -115
- warp/examples/fem/example_burgers.py +262 -0
- warp/examples/fem/example_convection_diffusion.py +0 -2
- warp/examples/fem/example_convection_diffusion_dg.py +0 -2
- warp/examples/fem/example_deformed_geometry.py +0 -2
- warp/examples/fem/example_diffusion.py +0 -2
- warp/examples/fem/example_diffusion_3d.py +5 -4
- warp/examples/fem/example_diffusion_mgpu.py +0 -2
- warp/examples/fem/example_mixed_elasticity.py +0 -2
- warp/examples/fem/example_navier_stokes.py +0 -2
- warp/examples/fem/example_stokes.py +0 -2
- warp/examples/fem/example_stokes_transfer.py +0 -2
- warp/examples/optim/example_bounce.py +0 -2
- warp/examples/optim/example_cloth_throw.py +0 -2
- warp/examples/optim/example_diffray.py +0 -2
- warp/examples/optim/example_drone.py +0 -2
- warp/examples/optim/example_inverse_kinematics.py +0 -2
- warp/examples/optim/example_inverse_kinematics_torch.py +0 -2
- warp/examples/optim/example_spring_cage.py +0 -2
- warp/examples/optim/example_trajectory.py +0 -2
- warp/examples/optim/example_walker.py +0 -2
- warp/examples/sim/example_cartpole.py +0 -2
- warp/examples/sim/example_cloth.py +0 -2
- warp/examples/sim/example_granular.py +0 -2
- warp/examples/sim/example_granular_collision_sdf.py +0 -2
- warp/examples/sim/example_jacobian_ik.py +0 -2
- warp/examples/sim/example_particle_chain.py +0 -2
- warp/examples/sim/example_quadruped.py +0 -2
- warp/examples/sim/example_rigid_chain.py +0 -2
- warp/examples/sim/example_rigid_contact.py +0 -2
- warp/examples/sim/example_rigid_force.py +0 -2
- warp/examples/sim/example_rigid_gyroscopic.py +0 -2
- warp/examples/sim/example_rigid_soft_contact.py +0 -2
- warp/examples/sim/example_soft_body.py +0 -2
- warp/fem/__init__.py +1 -0
- warp/fem/cache.py +3 -1
- warp/fem/geometry/__init__.py +1 -0
- warp/fem/geometry/element.py +4 -0
- warp/fem/geometry/grid_3d.py +0 -4
- warp/fem/geometry/nanogrid.py +455 -0
- warp/fem/integrate.py +63 -9
- warp/fem/space/__init__.py +43 -158
- warp/fem/space/basis_space.py +34 -0
- warp/fem/space/collocated_function_space.py +1 -1
- warp/fem/space/grid_2d_function_space.py +13 -132
- warp/fem/space/grid_3d_function_space.py +16 -154
- warp/fem/space/hexmesh_function_space.py +37 -134
- warp/fem/space/nanogrid_function_space.py +202 -0
- warp/fem/space/quadmesh_2d_function_space.py +12 -119
- warp/fem/space/restriction.py +4 -1
- warp/fem/space/shape/__init__.py +77 -0
- warp/fem/space/shape/cube_shape_function.py +5 -15
- warp/fem/space/tetmesh_function_space.py +6 -76
- warp/fem/space/trimesh_2d_function_space.py +6 -76
- warp/native/array.h +12 -3
- warp/native/builtin.h +48 -5
- warp/native/bvh.cpp +14 -10
- warp/native/bvh.cu +23 -15
- warp/native/bvh.h +1 -0
- warp/native/clang/clang.cpp +2 -1
- warp/native/crt.cpp +11 -1
- warp/native/crt.h +18 -1
- warp/native/exports.h +187 -0
- warp/native/mat.h +47 -0
- warp/native/mesh.cpp +1 -1
- warp/native/mesh.cu +1 -2
- warp/native/nanovdb/GridHandle.h +366 -0
- warp/native/nanovdb/HostBuffer.h +590 -0
- warp/native/nanovdb/NanoVDB.h +3999 -2157
- warp/native/nanovdb/PNanoVDB.h +936 -99
- warp/native/quat.h +28 -1
- warp/native/rand.h +5 -1
- warp/native/vec.h +45 -1
- warp/native/volume.cpp +335 -103
- warp/native/volume.cu +39 -13
- warp/native/volume.h +725 -303
- warp/native/volume_builder.cu +381 -360
- warp/native/volume_builder.h +16 -1
- warp/native/volume_impl.h +61 -0
- warp/native/warp.cu +8 -2
- warp/native/warp.h +15 -7
- warp/render/render_opengl.py +191 -52
- warp/sim/integrator_featherstone.py +10 -3
- warp/sim/integrator_xpbd.py +16 -22
- warp/sparse.py +89 -27
- warp/stubs.py +83 -0
- warp/tests/assets/test_index_grid.nvdb +0 -0
- warp/tests/aux_test_dependent.py +0 -2
- warp/tests/aux_test_grad_customs.py +0 -2
- warp/tests/aux_test_reference.py +0 -2
- warp/tests/aux_test_reference_reference.py +0 -2
- warp/tests/aux_test_square.py +0 -2
- warp/tests/disabled_kinematics.py +0 -2
- warp/tests/test_adam.py +0 -2
- warp/tests/test_arithmetic.py +0 -36
- warp/tests/test_array.py +9 -11
- warp/tests/test_array_reduce.py +0 -2
- warp/tests/test_async.py +0 -2
- warp/tests/test_atomic.py +0 -2
- warp/tests/test_bool.py +58 -50
- warp/tests/test_builtins_resolution.py +0 -2
- warp/tests/test_bvh.py +0 -2
- warp/tests/test_closest_point_edge_edge.py +0 -1
- warp/tests/test_codegen.py +0 -4
- warp/tests/test_compile_consts.py +130 -10
- warp/tests/test_conditional.py +0 -2
- warp/tests/test_copy.py +0 -2
- warp/tests/test_ctypes.py +6 -8
- warp/tests/test_dense.py +0 -2
- warp/tests/test_devices.py +0 -2
- warp/tests/test_dlpack.py +9 -11
- warp/tests/test_examples.py +42 -39
- warp/tests/test_fabricarray.py +0 -3
- warp/tests/test_fast_math.py +0 -2
- warp/tests/test_fem.py +75 -54
- warp/tests/test_fp16.py +0 -2
- warp/tests/test_func.py +0 -2
- warp/tests/test_generics.py +27 -2
- warp/tests/test_grad.py +147 -8
- warp/tests/test_grad_customs.py +0 -2
- warp/tests/test_hash_grid.py +1 -3
- warp/tests/test_import.py +0 -2
- warp/tests/test_indexedarray.py +0 -2
- warp/tests/test_intersect.py +0 -2
- warp/tests/test_jax.py +0 -2
- warp/tests/test_large.py +11 -9
- warp/tests/test_launch.py +0 -2
- warp/tests/test_lerp.py +10 -54
- warp/tests/test_linear_solvers.py +3 -5
- warp/tests/test_lvalue.py +0 -2
- warp/tests/test_marching_cubes.py +0 -2
- warp/tests/test_mat.py +0 -2
- warp/tests/test_mat_lite.py +0 -2
- warp/tests/test_mat_scalar_ops.py +0 -2
- warp/tests/test_math.py +0 -2
- warp/tests/test_matmul.py +35 -37
- warp/tests/test_matmul_lite.py +29 -31
- warp/tests/test_mempool.py +0 -2
- warp/tests/test_mesh.py +0 -3
- warp/tests/test_mesh_query_aabb.py +0 -2
- warp/tests/test_mesh_query_point.py +0 -2
- warp/tests/test_mesh_query_ray.py +0 -2
- warp/tests/test_mlp.py +0 -2
- warp/tests/test_model.py +0 -2
- warp/tests/test_module_hashing.py +111 -0
- warp/tests/test_modules_lite.py +0 -3
- warp/tests/test_multigpu.py +0 -2
- warp/tests/test_noise.py +0 -4
- warp/tests/test_operators.py +0 -2
- warp/tests/test_options.py +0 -2
- warp/tests/test_peer.py +0 -2
- warp/tests/test_pinned.py +0 -2
- warp/tests/test_print.py +0 -2
- warp/tests/test_quat.py +0 -2
- warp/tests/test_rand.py +41 -5
- warp/tests/test_reload.py +0 -10
- warp/tests/test_rounding.py +0 -2
- warp/tests/test_runlength_encode.py +0 -2
- warp/tests/test_sim_grad.py +0 -2
- warp/tests/test_sim_kinematics.py +0 -2
- warp/tests/test_smoothstep.py +0 -2
- warp/tests/test_snippet.py +0 -2
- warp/tests/test_sparse.py +0 -2
- warp/tests/test_spatial.py +0 -2
- warp/tests/test_special_values.py +362 -0
- warp/tests/test_streams.py +0 -2
- warp/tests/test_struct.py +0 -2
- warp/tests/test_tape.py +0 -2
- warp/tests/test_torch.py +0 -2
- warp/tests/test_transient_module.py +0 -2
- warp/tests/test_types.py +0 -2
- warp/tests/test_utils.py +0 -2
- warp/tests/test_vec.py +0 -2
- warp/tests/test_vec_lite.py +0 -2
- warp/tests/test_vec_scalar_ops.py +0 -2
- warp/tests/test_verify_fp.py +0 -2
- warp/tests/test_volume.py +237 -13
- warp/tests/test_volume_write.py +86 -3
- warp/tests/unittest_serial.py +10 -9
- warp/tests/unittest_suites.py +6 -2
- warp/tests/unittest_utils.py +2 -171
- warp/tests/unused_test_misc.py +0 -2
- warp/tests/walkthrough_debug.py +1 -1
- warp/thirdparty/unittest_parallel.py +37 -40
- warp/types.py +514 -77
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/METADATA +57 -30
- warp_lang-1.2.0.dist-info/RECORD +359 -0
- warp/examples/fem/example_convection_diffusion_dg0.py +0 -204
- warp/native/nanovdb/PNanoVDBWrite.h +0 -295
- warp_lang-1.1.0.dist-info/RECORD +0 -352
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
###########################################################################
|
|
9
9
|
# Example APIC Fluid Simulation
|
|
10
10
|
#
|
|
11
|
-
# Shows how to implement a
|
|
11
|
+
# Shows how to implement a minimalist APIC fluid simulation using a NanoVDB
|
|
12
|
+
# grid and the PicQuadrature class.
|
|
12
13
|
###########################################################################
|
|
13
14
|
|
|
14
15
|
import numpy as np
|
|
@@ -16,16 +17,22 @@ import numpy as np
|
|
|
16
17
|
import warp as wp
|
|
17
18
|
import warp.fem as fem
|
|
18
19
|
import warp.sim.render
|
|
19
|
-
from warp.fem import Domain, Field, Sample, at_node, div, grad, integrand
|
|
20
|
+
from warp.fem import Domain, Field, Sample, at_node, div, grad, integrand
|
|
20
21
|
from warp.sim import Model, State
|
|
21
|
-
from warp.sparse import BsrMatrix,
|
|
22
|
+
from warp.sparse import BsrMatrix, bsr_mm, bsr_mv, bsr_transposed
|
|
22
23
|
|
|
23
24
|
try:
|
|
24
25
|
from .bsr_utils import bsr_cg
|
|
25
26
|
except ImportError:
|
|
26
27
|
from bsr_utils import bsr_cg
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
@wp.func
|
|
31
|
+
def collision_sdf(x: wp.vec3):
|
|
32
|
+
# Arbitrary sdf representing collision geometry
|
|
33
|
+
# Here an inverted half-ball of radius 10
|
|
34
|
+
x[1] = wp.min(x[1], 0.0)
|
|
35
|
+
return 10.0 - wp.length(x), -wp.normalize(x)
|
|
29
36
|
|
|
30
37
|
|
|
31
38
|
@integrand
|
|
@@ -48,6 +55,13 @@ def integrate_velocity(
|
|
|
48
55
|
vel_apic = velocities[s.qp_index] + velocity_gradients[s.qp_index] * node_offset
|
|
49
56
|
|
|
50
57
|
vel_adv = vel_apic + dt * gravity
|
|
58
|
+
|
|
59
|
+
# if inside collider, remove normal velocity
|
|
60
|
+
sdf, sdf_gradient = collision_sdf(domain(s))
|
|
61
|
+
if sdf <= 0:
|
|
62
|
+
v_n = wp.dot(vel_adv, sdf_gradient)
|
|
63
|
+
vel_adv -= wp.max(v_n, 0.0) * sdf_gradient
|
|
64
|
+
|
|
51
65
|
return wp.dot(u(s), vel_adv)
|
|
52
66
|
|
|
53
67
|
|
|
@@ -63,31 +77,33 @@ def update_particles(
|
|
|
63
77
|
vel_grad: wp.array(dtype=wp.mat33),
|
|
64
78
|
):
|
|
65
79
|
"""Read particle velocity from grid and advect positions"""
|
|
66
|
-
|
|
80
|
+
p_vel = grid_vel(s)
|
|
67
81
|
vel_grad[s.qp_index] = grad(grid_vel, s)
|
|
68
82
|
|
|
69
|
-
pos_adv = pos_prev[s.qp_index] + dt *
|
|
83
|
+
pos_adv = pos_prev[s.qp_index] + dt * p_vel
|
|
70
84
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
pos[s.qp_index] = pos_proj
|
|
85
|
+
pos[s.qp_index] = pos_adv
|
|
86
|
+
vel[s.qp_index] = p_vel
|
|
74
87
|
|
|
75
88
|
|
|
76
89
|
@integrand
|
|
77
90
|
def velocity_boundary_projector_form(s: Sample, domain: Domain, u: Field, v: Field):
|
|
78
91
|
"""Projector for velocity-Dirichlet boundary conditions"""
|
|
79
92
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
x = domain(s)
|
|
94
|
+
sdf, sdf_normal = collision_sdf(x)
|
|
95
|
+
|
|
96
|
+
if sdf > 0.0:
|
|
97
|
+
# Neuman
|
|
83
98
|
return 0.0
|
|
84
99
|
|
|
85
|
-
# Free-slip on
|
|
86
|
-
return wp.dot(u(s),
|
|
100
|
+
# Free-slip on boundary
|
|
101
|
+
return wp.dot(u(s), sdf_normal) * wp.dot(v(s), sdf_normal)
|
|
87
102
|
|
|
88
103
|
|
|
89
104
|
@integrand
|
|
90
|
-
def divergence_form(s: Sample, u: Field, psi: Field):
|
|
105
|
+
def divergence_form(s: Sample, domain: Domain, u: Field, psi: Field):
|
|
106
|
+
# Divergence bilinear form
|
|
91
107
|
return div(u, s) * psi(s)
|
|
92
108
|
|
|
93
109
|
|
|
@@ -95,10 +111,7 @@ def divergence_form(s: Sample, u: Field, psi: Field):
|
|
|
95
111
|
def invert_volume_kernel(values: wp.array(dtype=float)):
|
|
96
112
|
i = wp.tid()
|
|
97
113
|
m = values[i]
|
|
98
|
-
|
|
99
|
-
values[i] = 0.0
|
|
100
|
-
else:
|
|
101
|
-
values[i] = 1.0 / m
|
|
114
|
+
values[i] = wp.select(m == 0.0, 1.0 / m, 0.0)
|
|
102
115
|
|
|
103
116
|
|
|
104
117
|
@wp.kernel
|
|
@@ -117,6 +130,8 @@ def scale_transposed_divergence_mat(
|
|
|
117
130
|
tr_divergence_mat_values: wp.array(dtype=wp.mat(shape=(3, 1), dtype=float)),
|
|
118
131
|
inv_fraction_int: wp.array(dtype=float),
|
|
119
132
|
):
|
|
133
|
+
# In-place scaling of gradient operator rows wiht inverse mass
|
|
134
|
+
|
|
120
135
|
u_i = wp.tid()
|
|
121
136
|
block_beg = tr_divergence_mat_offsets[u_i]
|
|
122
137
|
block_end = tr_divergence_mat_offsets[u_i + 1]
|
|
@@ -125,6 +140,15 @@ def scale_transposed_divergence_mat(
|
|
|
125
140
|
tr_divergence_mat_values[b] = tr_divergence_mat_values[b] * inv_fraction_int[u_i]
|
|
126
141
|
|
|
127
142
|
|
|
143
|
+
@wp.kernel
|
|
144
|
+
def compute_particle_ijk(positions: wp.array(dtype=wp.vec3), voxel_size: float, ijks: wp.array(dtype=wp.vec3i)):
|
|
145
|
+
# Index-space coordinates of grid cell containing each particle
|
|
146
|
+
|
|
147
|
+
p = wp.tid()
|
|
148
|
+
pos = positions[p] / voxel_size
|
|
149
|
+
ijks[p] = wp.vec3i(int(wp.floor(pos[0])), int(wp.floor(pos[1])), int(wp.floor(pos[2])))
|
|
150
|
+
|
|
151
|
+
|
|
128
152
|
def solve_incompressibility(divergence_mat: BsrMatrix, inv_volume, pressure, velocity, quiet: bool = False):
|
|
129
153
|
"""Solve for divergence-free velocity delta:
|
|
130
154
|
|
|
@@ -144,43 +168,45 @@ def solve_incompressibility(divergence_mat: BsrMatrix, inv_volume, pressure, vel
|
|
|
144
168
|
],
|
|
145
169
|
)
|
|
146
170
|
|
|
147
|
-
# For simplicity, assemble
|
|
171
|
+
# For simplicity, assemble Schur complement and solve with CG
|
|
148
172
|
schur = bsr_mm(divergence_mat, transposed_divergence_mat)
|
|
149
173
|
|
|
150
174
|
rhs = wp.zeros_like(pressure)
|
|
151
175
|
bsr_mv(A=divergence_mat, x=velocity, y=rhs, alpha=-1.0, beta=0.0)
|
|
152
|
-
bsr_cg(schur, b=rhs, x=pressure, quiet=quiet)
|
|
176
|
+
bsr_cg(schur, b=rhs, x=pressure, quiet=quiet, tol=1.0e-6)
|
|
153
177
|
|
|
154
178
|
# Apply pressure to velocity
|
|
155
179
|
bsr_mv(A=transposed_divergence_mat, x=pressure, y=velocity, alpha=1.0, beta=1.0)
|
|
156
180
|
|
|
157
181
|
|
|
158
182
|
class Example:
|
|
159
|
-
def __init__(self, quiet=False, stage_path="example_apic_fluid.usd",
|
|
183
|
+
def __init__(self, quiet=False, stage_path="example_apic_fluid.usd", voxel_size=1.0):
|
|
160
184
|
fps = 60
|
|
161
185
|
self.frame_dt = 1.0 / fps
|
|
162
186
|
self.current_frame = 0
|
|
163
187
|
|
|
164
188
|
self.sim_substeps = 1
|
|
165
189
|
self.sim_dt = self.frame_dt / self.sim_substeps
|
|
190
|
+
self.voxel_size = voxel_size
|
|
166
191
|
|
|
167
192
|
self._quiet = quiet
|
|
168
193
|
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
grid_lo = wp.vec3(0.0)
|
|
173
|
-
grid_hi = wp.vec3(50, 100, 25)
|
|
194
|
+
# particle emission
|
|
195
|
+
particle_grid_lo = wp.vec3(-5)
|
|
196
|
+
particle_grid_hi = wp.vec3(5)
|
|
174
197
|
|
|
175
|
-
grid_cell_size =
|
|
198
|
+
grid_cell_size = voxel_size
|
|
176
199
|
grid_cell_volume = np.prod(grid_cell_size)
|
|
177
200
|
|
|
178
|
-
PARTICLES_PER_CELL_DIM =
|
|
201
|
+
PARTICLES_PER_CELL_DIM = 2
|
|
179
202
|
self.radius = float(np.max(grid_cell_size) / (2 * PARTICLES_PER_CELL_DIM))
|
|
180
203
|
|
|
181
|
-
particle_grid_res =
|
|
204
|
+
particle_grid_res = (
|
|
205
|
+
np.array((particle_grid_hi - particle_grid_lo) / voxel_size, dtype=int) * PARTICLES_PER_CELL_DIM
|
|
206
|
+
)
|
|
182
207
|
particle_grid_offset = wp.vec3(self.radius, self.radius, self.radius)
|
|
183
208
|
|
|
209
|
+
# Initialize warp.sim model, spawn particles
|
|
184
210
|
np.random.seed(0)
|
|
185
211
|
builder = wp.sim.ModelBuilder()
|
|
186
212
|
builder.add_particle_grid(
|
|
@@ -190,60 +216,17 @@ class Example:
|
|
|
190
216
|
cell_x=self.radius * 2.0,
|
|
191
217
|
cell_y=self.radius * 2.0,
|
|
192
218
|
cell_z=self.radius * 2.0,
|
|
193
|
-
pos=
|
|
219
|
+
pos=particle_grid_lo + particle_grid_offset,
|
|
194
220
|
rot=wp.quat_identity(),
|
|
195
221
|
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
196
222
|
mass=grid_cell_volume / PARTICLES_PER_CELL_DIM**3,
|
|
197
223
|
jitter=self.radius * 1.0,
|
|
198
|
-
radius_mean=self.radius,
|
|
199
|
-
)
|
|
200
|
-
|
|
201
|
-
self.grid = fem.Grid3D(wp.vec3i(grid_res), grid_lo, grid_hi)
|
|
202
|
-
|
|
203
|
-
# Function spaces
|
|
204
|
-
self.velocity_space = fem.make_polynomial_space(self.grid, dtype=wp.vec3, degree=1)
|
|
205
|
-
self.fraction_space = fem.make_polynomial_space(self.grid, dtype=float, degree=1)
|
|
206
|
-
self.strain_space = fem.make_polynomial_space(
|
|
207
|
-
self.grid,
|
|
208
|
-
dtype=float,
|
|
209
|
-
degree=0,
|
|
210
224
|
)
|
|
211
|
-
|
|
212
|
-
self.pressure_field = self.strain_space.make_field()
|
|
213
|
-
self.velocity_field = self.velocity_space.make_field()
|
|
214
|
-
|
|
215
|
-
# Test and trial functions
|
|
216
|
-
self.domain = fem.Cells(self.grid)
|
|
217
|
-
self.velocity_test = fem.make_test(self.velocity_space, domain=self.domain)
|
|
218
|
-
self.velocity_trial = fem.make_trial(self.velocity_space, domain=self.domain)
|
|
219
|
-
self.fraction_test = fem.make_test(self.fraction_space, domain=self.domain)
|
|
220
|
-
self.strain_test = fem.make_test(self.strain_space, domain=self.domain)
|
|
221
|
-
self.strain_trial = fem.make_trial(self.strain_space, domain=self.domain)
|
|
222
|
-
|
|
223
|
-
# Enforcing the Dirichlet boundary condition the hard way;
|
|
224
|
-
# build projector for velocity left- and right-hand-sides
|
|
225
|
-
boundary = fem.BoundarySides(self.grid)
|
|
226
|
-
u_bd_test = fem.make_test(space=self.velocity_space, domain=boundary)
|
|
227
|
-
u_bd_trial = fem.make_trial(space=self.velocity_space, domain=boundary)
|
|
228
|
-
u_bd_projector = fem.integrate(
|
|
229
|
-
velocity_boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True, output_dtype=float
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
fem.normalize_dirichlet_projector(u_bd_projector)
|
|
233
|
-
self.vel_bd_projector = u_bd_projector
|
|
225
|
+
self.model: Model = builder.finalize()
|
|
234
226
|
|
|
235
227
|
# Storage for temporary variables
|
|
236
228
|
self.temporary_store = fem.TemporaryStore()
|
|
237
229
|
|
|
238
|
-
self._divergence_matrix = bsr_zeros(
|
|
239
|
-
self.strain_space.node_count(),
|
|
240
|
-
self.velocity_space.node_count(),
|
|
241
|
-
block_type=wp.mat(shape=(1, 3), dtype=float),
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
# Warp.sim model
|
|
245
|
-
self.model: Model = builder.finalize()
|
|
246
|
-
|
|
247
230
|
if not self._quiet:
|
|
248
231
|
print("Particle count:", self.model.particle_count)
|
|
249
232
|
|
|
@@ -265,79 +248,122 @@ class Example:
|
|
|
265
248
|
fem.set_default_temporary_store(self.temporary_store)
|
|
266
249
|
|
|
267
250
|
self.current_frame = self.current_frame + 1
|
|
251
|
+
|
|
252
|
+
particle_ijk = wp.empty(self.state_0.particle_count, dtype=wp.vec3i)
|
|
253
|
+
|
|
268
254
|
with wp.ScopedTimer(f"simulate frame {self.current_frame}", active=True):
|
|
269
255
|
for _s in range(self.sim_substeps):
|
|
270
|
-
#
|
|
271
|
-
|
|
272
|
-
|
|
256
|
+
# Compute the voxel coordinates for each particle.
|
|
257
|
+
# `Volume.allocate_by_voxels` accepts world positions, but allocates
|
|
258
|
+
# the voxels with the closest origin rather than the enclosing ones
|
|
259
|
+
# (i.e, it "round"s the positions, while here we eant to "floor" it)
|
|
260
|
+
wp.launch(
|
|
261
|
+
compute_particle_ijk,
|
|
262
|
+
dim=particle_ijk.shape,
|
|
263
|
+
inputs=[self.state_0.particle_q, self.voxel_size, particle_ijk],
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Allocate the voxels and create the warp.fem geometry
|
|
267
|
+
volume = wp.Volume.allocate_by_voxels(
|
|
268
|
+
voxel_points=particle_ijk,
|
|
269
|
+
voxel_size=self.voxel_size,
|
|
270
|
+
)
|
|
271
|
+
grid = fem.Nanogrid(volume)
|
|
272
|
+
|
|
273
|
+
# Define function spaces: linear (Q1) for velocity and volume fraction,
|
|
274
|
+
# piecewise-constant for pressure
|
|
275
|
+
linear_basis_space = fem.make_polynomial_basis_space(grid, degree=1)
|
|
276
|
+
velocity_space = fem.make_collocated_function_space(linear_basis_space, dtype=wp.vec3)
|
|
277
|
+
fraction_space = fem.make_collocated_function_space(linear_basis_space, dtype=float)
|
|
278
|
+
strain_space = fem.make_polynomial_space(
|
|
279
|
+
grid,
|
|
280
|
+
dtype=float,
|
|
281
|
+
degree=0,
|
|
282
|
+
discontinuous=True,
|
|
273
283
|
)
|
|
274
284
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
285
|
+
pressure_field = strain_space.make_field()
|
|
286
|
+
velocity_field = velocity_space.make_field()
|
|
287
|
+
|
|
288
|
+
# Define test and trial functions and integrating linear and bilinear forms
|
|
289
|
+
domain = fem.Cells(grid)
|
|
290
|
+
velocity_test = fem.make_test(velocity_space, domain=domain)
|
|
291
|
+
velocity_trial = fem.make_trial(velocity_space, domain=domain)
|
|
292
|
+
fraction_test = fem.make_test(fraction_space, domain=domain)
|
|
293
|
+
strain_test = fem.make_test(strain_space, domain=domain)
|
|
294
|
+
|
|
295
|
+
# Build projector for Dirichlet boundary conditions
|
|
296
|
+
vel_projector = fem.integrate(
|
|
297
|
+
velocity_boundary_projector_form,
|
|
298
|
+
fields={"u": velocity_trial, "v": velocity_test},
|
|
299
|
+
nodal=True,
|
|
300
|
+
output_dtype=float,
|
|
278
301
|
)
|
|
279
|
-
|
|
280
|
-
|
|
302
|
+
fem.normalize_dirichlet_projector(vel_projector)
|
|
303
|
+
|
|
304
|
+
# Bin particles to grid cells
|
|
305
|
+
pic = fem.PicQuadrature(
|
|
306
|
+
domain=domain, positions=self.state_0.particle_q, measures=self.model.particle_mass
|
|
281
307
|
)
|
|
282
|
-
inv_volume = inv_volume_temporary.array
|
|
283
|
-
velocity_int = velocity_int_temporary.array
|
|
284
308
|
|
|
285
|
-
#
|
|
286
|
-
fem.integrate(
|
|
309
|
+
# Compute inverse particle volume for each grid node
|
|
310
|
+
inv_volume = fem.integrate(
|
|
287
311
|
integrate_fraction,
|
|
288
312
|
quadrature=pic,
|
|
289
|
-
fields={"phi":
|
|
290
|
-
|
|
291
|
-
output=inv_volume,
|
|
313
|
+
fields={"phi": fraction_test},
|
|
314
|
+
output_dtype=float,
|
|
292
315
|
)
|
|
293
316
|
wp.launch(kernel=invert_volume_kernel, dim=inv_volume.shape, inputs=[inv_volume])
|
|
294
317
|
|
|
295
318
|
# Velocity right-hand side
|
|
296
|
-
fem.integrate(
|
|
319
|
+
velocity_int = fem.integrate(
|
|
297
320
|
integrate_velocity,
|
|
298
321
|
quadrature=pic,
|
|
299
|
-
fields={"u":
|
|
322
|
+
fields={"u": velocity_test},
|
|
300
323
|
values={
|
|
301
324
|
"velocities": self.state_0.particle_qd,
|
|
302
325
|
"velocity_gradients": self.state_0.particle_qd_grad,
|
|
303
326
|
"dt": self.sim_dt,
|
|
304
327
|
"gravity": self.model.gravity,
|
|
305
328
|
},
|
|
306
|
-
|
|
307
|
-
output=velocity_int,
|
|
329
|
+
output_dtype=wp.vec3,
|
|
308
330
|
)
|
|
309
331
|
|
|
310
332
|
# Compute constraint-free velocity
|
|
311
333
|
wp.launch(
|
|
312
334
|
kernel=scalar_vector_multiply,
|
|
313
335
|
dim=inv_volume.shape[0],
|
|
314
|
-
inputs=[inv_volume, velocity_int,
|
|
336
|
+
inputs=[inv_volume, velocity_int, velocity_field.dof_values],
|
|
315
337
|
)
|
|
316
338
|
|
|
317
339
|
# Apply velocity boundary conditions:
|
|
318
|
-
# velocity -=
|
|
319
|
-
|
|
320
|
-
|
|
340
|
+
# velocity -= vel_projector * velocity
|
|
341
|
+
bsr_mv(
|
|
342
|
+
A=vel_projector,
|
|
343
|
+
x=velocity_field.dof_values,
|
|
344
|
+
y=velocity_field.dof_values,
|
|
345
|
+
alpha=-1.0,
|
|
346
|
+
beta=1.0,
|
|
347
|
+
)
|
|
321
348
|
|
|
322
|
-
#
|
|
323
|
-
fem.integrate(
|
|
349
|
+
# Assemble divergence operator matrix
|
|
350
|
+
divergence_matrix = fem.integrate(
|
|
324
351
|
divergence_form,
|
|
325
352
|
quadrature=pic,
|
|
326
|
-
fields={"u":
|
|
327
|
-
|
|
328
|
-
output=self._divergence_matrix,
|
|
353
|
+
fields={"u": velocity_trial, "psi": strain_test},
|
|
354
|
+
output_dtype=float,
|
|
329
355
|
)
|
|
330
356
|
|
|
331
357
|
# Project matrix to enforce boundary conditions
|
|
332
|
-
|
|
333
|
-
bsr_mm(alpha=-1.0, x=
|
|
358
|
+
# divergence_matrix -= divergence_matrix * vel_projector
|
|
359
|
+
bsr_mm(alpha=-1.0, x=divergence_matrix, y=vel_projector, z=divergence_matrix, beta=1.0)
|
|
334
360
|
|
|
335
361
|
# Solve unilateral incompressibility
|
|
336
362
|
solve_incompressibility(
|
|
337
|
-
|
|
363
|
+
divergence_matrix,
|
|
338
364
|
inv_volume,
|
|
339
|
-
|
|
340
|
-
|
|
365
|
+
pressure_field.dof_values,
|
|
366
|
+
velocity_field.dof_values,
|
|
341
367
|
quiet=self._quiet,
|
|
342
368
|
)
|
|
343
369
|
|
|
@@ -352,7 +378,7 @@ class Example:
|
|
|
352
378
|
"vel_grad": self.state_1.particle_qd_grad,
|
|
353
379
|
"dt": self.sim_dt,
|
|
354
380
|
},
|
|
355
|
-
fields={"grid_vel":
|
|
381
|
+
fields={"grid_vel": velocity_field},
|
|
356
382
|
)
|
|
357
383
|
|
|
358
384
|
# swap states
|
|
@@ -385,19 +411,18 @@ if __name__ == "__main__":
|
|
|
385
411
|
default="example_apic_fluid.usd",
|
|
386
412
|
help="Path to the output USD file.",
|
|
387
413
|
)
|
|
388
|
-
parser.add_argument("--num_frames", type=int, default=
|
|
414
|
+
parser.add_argument("--num_frames", type=int, default=250, help="Total number of frames.")
|
|
389
415
|
parser.add_argument("--quiet", action="store_true")
|
|
390
416
|
parser.add_argument(
|
|
391
|
-
"--
|
|
392
|
-
type=
|
|
393
|
-
default=
|
|
394
|
-
help="Delimited list specifying resolution in x, y, and z.",
|
|
417
|
+
"--voxel_size",
|
|
418
|
+
type=float,
|
|
419
|
+
default=0.25,
|
|
395
420
|
)
|
|
396
421
|
|
|
397
422
|
args = parser.parse_known_args()[0]
|
|
398
423
|
|
|
399
424
|
with wp.ScopedDevice(args.device):
|
|
400
|
-
example = Example(quiet=args.quiet, stage_path=args.stage_path,
|
|
425
|
+
example = Example(quiet=args.quiet, stage_path=args.stage_path, voxel_size=args.voxel_size)
|
|
401
426
|
|
|
402
427
|
for _ in range(args.num_frames):
|
|
403
428
|
example.step()
|