warp-lang 1.0.0b2__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__py3-none-manylinux2014_x86_64.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.
- docs/conf.py +17 -5
- examples/env/env_ant.py +1 -1
- examples/env/env_cartpole.py +1 -1
- examples/env/env_humanoid.py +1 -1
- examples/env/env_usd.py +4 -1
- examples/env/environment.py +8 -9
- examples/example_dem.py +34 -33
- examples/example_diffray.py +364 -337
- examples/example_fluid.py +32 -23
- examples/example_jacobian_ik.py +97 -93
- examples/example_marching_cubes.py +6 -16
- examples/example_mesh.py +6 -16
- examples/example_mesh_intersect.py +16 -14
- examples/example_nvdb.py +14 -16
- examples/example_raycast.py +14 -13
- examples/example_raymarch.py +16 -23
- examples/example_render_opengl.py +19 -10
- examples/example_sim_cartpole.py +82 -78
- examples/example_sim_cloth.py +45 -48
- examples/example_sim_fk_grad.py +51 -44
- examples/example_sim_fk_grad_torch.py +47 -40
- examples/example_sim_grad_bounce.py +108 -133
- examples/example_sim_grad_cloth.py +99 -113
- examples/example_sim_granular.py +5 -6
- examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
- examples/example_sim_neo_hookean.py +51 -55
- examples/example_sim_particle_chain.py +4 -4
- examples/example_sim_quadruped.py +126 -81
- examples/example_sim_rigid_chain.py +54 -61
- examples/example_sim_rigid_contact.py +66 -70
- examples/example_sim_rigid_fem.py +3 -3
- examples/example_sim_rigid_force.py +1 -1
- examples/example_sim_rigid_gyroscopic.py +3 -4
- examples/example_sim_rigid_kinematics.py +28 -39
- examples/example_sim_trajopt.py +112 -110
- examples/example_sph.py +9 -8
- examples/example_wave.py +7 -7
- examples/fem/bsr_utils.py +30 -17
- examples/fem/example_apic_fluid.py +85 -69
- examples/fem/example_convection_diffusion.py +97 -93
- examples/fem/example_convection_diffusion_dg.py +142 -149
- examples/fem/example_convection_diffusion_dg0.py +141 -136
- examples/fem/example_deformed_geometry.py +146 -0
- examples/fem/example_diffusion.py +115 -84
- examples/fem/example_diffusion_3d.py +116 -86
- examples/fem/example_diffusion_mgpu.py +102 -79
- examples/fem/example_mixed_elasticity.py +139 -100
- examples/fem/example_navier_stokes.py +175 -162
- examples/fem/example_stokes.py +143 -111
- examples/fem/example_stokes_transfer.py +186 -157
- examples/fem/mesh_utils.py +59 -97
- examples/fem/plot_utils.py +138 -17
- tools/ci/publishing/build_nodes_info.py +54 -0
- warp/__init__.py +4 -3
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +5 -3
- warp/build_dll.py +29 -9
- warp/builtins.py +836 -492
- warp/codegen.py +864 -553
- warp/config.py +3 -1
- warp/context.py +389 -172
- warp/fem/__init__.py +24 -6
- warp/fem/cache.py +318 -25
- warp/fem/dirichlet.py +7 -3
- warp/fem/domain.py +14 -0
- warp/fem/field/__init__.py +30 -38
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +244 -138
- warp/fem/field/restriction.py +8 -6
- warp/fem/field/test.py +127 -59
- warp/fem/field/trial.py +117 -60
- warp/fem/geometry/__init__.py +5 -1
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +24 -1
- warp/fem/geometry/geometry.py +86 -14
- warp/fem/geometry/grid_2d.py +112 -54
- warp/fem/geometry/grid_3d.py +134 -65
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +85 -33
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +451 -115
- warp/fem/geometry/trimesh_2d.py +197 -92
- warp/fem/integrate.py +534 -268
- warp/fem/operator.py +58 -31
- warp/fem/polynomial.py +11 -0
- warp/fem/quadrature/__init__.py +1 -1
- warp/fem/quadrature/pic_quadrature.py +150 -58
- warp/fem/quadrature/quadrature.py +209 -57
- warp/fem/space/__init__.py +230 -53
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +49 -2
- warp/fem/space/function_space.py +90 -39
- warp/fem/space/grid_2d_function_space.py +149 -496
- warp/fem/space/grid_3d_function_space.py +173 -538
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +129 -76
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +46 -34
- warp/fem/space/shape/__init__.py +15 -0
- warp/fem/space/shape/cube_shape_function.py +738 -0
- warp/fem/space/shape/shape_function.py +103 -0
- warp/fem/space/shape/square_shape_function.py +611 -0
- warp/fem/space/shape/tet_shape_function.py +567 -0
- warp/fem/space/shape/triangle_shape_function.py +429 -0
- warp/fem/space/tetmesh_function_space.py +132 -1039
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +104 -742
- warp/fem/types.py +13 -11
- warp/fem/utils.py +335 -60
- warp/native/array.h +120 -34
- warp/native/builtin.h +101 -72
- warp/native/bvh.cpp +73 -325
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +22 -40
- warp/native/clang/clang.cpp +1 -0
- warp/native/crt.h +2 -0
- warp/native/cuda_util.cpp +8 -3
- warp/native/cuda_util.h +1 -0
- warp/native/exports.h +1522 -1243
- warp/native/intersect.h +19 -4
- warp/native/intersect_adj.h +8 -8
- warp/native/mat.h +76 -17
- warp/native/mesh.cpp +33 -108
- warp/native/mesh.cu +114 -18
- warp/native/mesh.h +395 -40
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +44 -34
- warp/native/reduce.cpp +1 -1
- warp/native/sparse.cpp +4 -4
- warp/native/sparse.cu +163 -155
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +18 -14
- warp/native/vec.h +103 -21
- warp/native/warp.cpp +2 -1
- warp/native/warp.cu +28 -3
- warp/native/warp.h +4 -3
- warp/render/render_opengl.py +261 -109
- warp/sim/__init__.py +1 -2
- warp/sim/articulation.py +385 -185
- warp/sim/import_mjcf.py +59 -48
- warp/sim/import_urdf.py +15 -15
- warp/sim/import_usd.py +174 -102
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_xpbd.py +4 -3
- warp/sim/model.py +330 -250
- warp/sim/render.py +1 -1
- warp/sparse.py +625 -152
- warp/stubs.py +341 -309
- warp/tape.py +9 -6
- warp/tests/__main__.py +3 -6
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/disabled_kinematics.py +239 -0
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +103 -106
- warp/tests/test_arithmetic.py +94 -74
- warp/tests/test_array.py +82 -101
- warp/tests/test_array_reduce.py +57 -23
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +22 -12
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +18 -18
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +165 -134
- warp/tests/test_compile_consts.py +28 -20
- warp/tests/test_conditional.py +108 -24
- warp/tests/test_copy.py +10 -12
- warp/tests/test_ctypes.py +112 -88
- warp/tests/test_dense.py +21 -14
- warp/tests/test_devices.py +98 -0
- warp/tests/test_dlpack.py +75 -75
- warp/tests/test_examples.py +237 -0
- warp/tests/test_fabricarray.py +22 -24
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1034 -124
- warp/tests/test_fp16.py +23 -16
- warp/tests/test_func.py +187 -86
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +123 -181
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +35 -34
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +24 -25
- warp/tests/test_intersect.py +18 -9
- warp/tests/test_large.py +141 -0
- warp/tests/test_launch.py +14 -41
- warp/tests/test_lerp.py +64 -65
- warp/tests/test_lvalue.py +493 -0
- warp/tests/test_marching_cubes.py +12 -13
- warp/tests/test_mat.py +517 -2898
- warp/tests/test_mat_lite.py +115 -0
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +103 -9
- warp/tests/test_matmul.py +304 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +60 -22
- warp/tests/test_mesh_query_aabb.py +21 -25
- warp/tests/test_mesh_query_point.py +111 -22
- warp/tests/test_mesh_query_ray.py +12 -24
- warp/tests/test_mlp.py +30 -22
- warp/tests/test_model.py +92 -89
- warp/tests/test_modules_lite.py +39 -0
- warp/tests/test_multigpu.py +88 -114
- warp/tests/test_noise.py +12 -11
- warp/tests/test_operators.py +16 -20
- warp/tests/test_options.py +11 -11
- warp/tests/test_pinned.py +17 -18
- warp/tests/test_print.py +32 -11
- warp/tests/test_quat.py +275 -129
- warp/tests/test_rand.py +18 -16
- warp/tests/test_reload.py +38 -34
- warp/tests/test_rounding.py +50 -43
- warp/tests/test_runlength_encode.py +168 -20
- warp/tests/test_smoothstep.py +9 -11
- warp/tests/test_snippet.py +143 -0
- warp/tests/test_sparse.py +261 -63
- warp/tests/test_spatial.py +276 -243
- warp/tests/test_streams.py +110 -85
- warp/tests/test_struct.py +268 -63
- warp/tests/test_tape.py +39 -21
- warp/tests/test_torch.py +90 -86
- warp/tests/test_transient_module.py +10 -12
- warp/tests/test_types.py +363 -0
- warp/tests/test_utils.py +451 -0
- warp/tests/test_vec.py +354 -2050
- warp/tests/test_vec_lite.py +73 -0
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +418 -376
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +291 -0
- warp/tests/unittest_utils.py +342 -0
- warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +589 -0
- warp/types.py +622 -211
- warp/utils.py +54 -393
- warp_lang-1.0.0b6.dist-info/METADATA +238 -0
- warp_lang-1.0.0b6.dist-info/RECORD +409 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
- examples/example_cache_management.py +0 -40
- examples/example_multigpu.py +0 -54
- examples/example_struct.py +0 -65
- examples/fem/example_stokes_transfer_3d.py +0 -210
- warp/fem/field/discrete_field.py +0 -80
- warp/fem/space/nodal_function_space.py +0 -233
- warp/tests/test_all.py +0 -223
- warp/tests/test_array_scan.py +0 -60
- warp/tests/test_base.py +0 -208
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- warp_lang-1.0.0b2.dist-info/METADATA +0 -26
- warp_lang-1.0.0b2.dist-info/RECORD +0 -378
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import math
|
|
3
|
-
from typing import Any
|
|
4
2
|
|
|
5
3
|
import warp as wp
|
|
6
4
|
import numpy as np
|
|
7
5
|
|
|
8
|
-
import warp.sim.render
|
|
9
6
|
from warp.sim import Model, State
|
|
7
|
+
import warp.sim.render
|
|
8
|
+
|
|
9
|
+
import warp.fem as fem
|
|
10
|
+
|
|
11
|
+
from warp.fem import integrand, lookup, normal, grad, at_node, div
|
|
12
|
+
from warp.fem import Field, Sample, Domain
|
|
10
13
|
|
|
11
|
-
from warp.
|
|
12
|
-
from warp.fem.domain import Cells, BoundarySides
|
|
13
|
-
from warp.fem.space import make_polynomial_space
|
|
14
|
-
from warp.fem.quadrature import PicQuadrature
|
|
15
|
-
from warp.fem.field import make_test, make_trial
|
|
16
|
-
from warp.fem.types import vec3i, Field, Sample, Domain
|
|
17
|
-
from warp.fem.integrate import integrate
|
|
18
|
-
from warp.fem.operator import integrand, lookup, normal, grad, at_node, div
|
|
19
|
-
from warp.fem.dirichlet import normalize_dirichlet_projector
|
|
14
|
+
from warp.sparse import bsr_mv, bsr_copy, bsr_mm, bsr_transposed, bsr_zeros, BsrMatrix
|
|
20
15
|
|
|
21
|
-
from warp.sparse import bsr_mv, bsr_copy, bsr_mm, bsr_transposed, BsrMatrix
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
try:
|
|
18
|
+
from .bsr_utils import bsr_cg
|
|
19
|
+
except ImportError:
|
|
20
|
+
from bsr_utils import bsr_cg
|
|
24
21
|
|
|
25
22
|
|
|
26
23
|
@integrand
|
|
@@ -67,8 +64,6 @@ def update_particles(
|
|
|
67
64
|
pos_proj = domain(lookup(domain, pos_adv))
|
|
68
65
|
pos[s.qp_index] = pos_proj
|
|
69
66
|
|
|
70
|
-
return 0.0
|
|
71
|
-
|
|
72
67
|
|
|
73
68
|
@integrand
|
|
74
69
|
def velocity_boundary_projector_form(s: Sample, domain: Domain, u: Field, v: Field):
|
|
@@ -122,12 +117,7 @@ def scale_transposed_divergence_mat(
|
|
|
122
117
|
tr_divergence_mat_values[b] = tr_divergence_mat_values[b] * inv_fraction_int[u_i]
|
|
123
118
|
|
|
124
119
|
|
|
125
|
-
def solve_incompressibility(
|
|
126
|
-
divergence_mat: BsrMatrix,
|
|
127
|
-
inv_volume,
|
|
128
|
-
pressure,
|
|
129
|
-
velocity,
|
|
130
|
-
):
|
|
120
|
+
def solve_incompressibility(divergence_mat: BsrMatrix, inv_volume, pressure, velocity, quiet: bool = False):
|
|
131
121
|
"""Solve for divergence-free velocity delta:
|
|
132
122
|
|
|
133
123
|
delta_velocity = inv_volume * transpose(divergence_mat) * pressure
|
|
@@ -151,24 +141,26 @@ def solve_incompressibility(
|
|
|
151
141
|
|
|
152
142
|
rhs = wp.zeros_like(pressure)
|
|
153
143
|
bsr_mv(A=divergence_mat, x=velocity, y=rhs, alpha=-1.0, beta=0.0)
|
|
154
|
-
bsr_cg(schur, b=rhs, x=pressure)
|
|
144
|
+
bsr_cg(schur, b=rhs, x=pressure, quiet=quiet)
|
|
155
145
|
|
|
156
146
|
# Apply pressure to velocity
|
|
157
147
|
bsr_mv(A=transposed_divergence_mat, x=pressure, y=velocity, alpha=1.0, beta=1.0)
|
|
158
148
|
|
|
159
149
|
|
|
160
150
|
class Example:
|
|
161
|
-
def __init__(self, stage):
|
|
151
|
+
def __init__(self, stage, num_frames=1000, res=[32, 64, 16], quiet=False):
|
|
162
152
|
self.frame_dt = 1.0 / 60
|
|
163
|
-
self.
|
|
153
|
+
self.num_frames = num_frames
|
|
154
|
+
self.current_frame = 0
|
|
164
155
|
|
|
165
156
|
self.sim_substeps = 1
|
|
166
157
|
self.sim_dt = self.frame_dt / self.sim_substeps
|
|
167
|
-
self.sim_steps = self.
|
|
168
|
-
|
|
158
|
+
self.sim_steps = self.num_frames * self.sim_substeps
|
|
159
|
+
|
|
160
|
+
self._quiet = quiet
|
|
169
161
|
|
|
170
162
|
# grid dimensions and particle emission
|
|
171
|
-
grid_res = np.array(
|
|
163
|
+
grid_res = np.array(res, dtype=int)
|
|
172
164
|
particle_fill_frac = np.array([0.5, 0.5, 1.0])
|
|
173
165
|
grid_lo = wp.vec3(0.0)
|
|
174
166
|
grid_hi = wp.vec3(50, 100, 25)
|
|
@@ -177,10 +169,10 @@ class Example:
|
|
|
177
169
|
grid_cell_volume = np.prod(grid_cell_size)
|
|
178
170
|
|
|
179
171
|
PARTICLES_PER_CELL_DIM = 3
|
|
180
|
-
self.radius = np.max(grid_cell_size) / (2 * PARTICLES_PER_CELL_DIM)
|
|
172
|
+
self.radius = float(np.max(grid_cell_size) / (2 * PARTICLES_PER_CELL_DIM))
|
|
181
173
|
|
|
182
174
|
particle_grid_res = np.array(particle_fill_frac * grid_res * PARTICLES_PER_CELL_DIM, dtype=int)
|
|
183
|
-
particle_grid_offset = self.radius
|
|
175
|
+
particle_grid_offset = wp.vec3(self.radius, self.radius, self.radius)
|
|
184
176
|
|
|
185
177
|
np.random.seed(0)
|
|
186
178
|
builder = wp.sim.ModelBuilder()
|
|
@@ -191,20 +183,20 @@ class Example:
|
|
|
191
183
|
cell_x=self.radius * 2.0,
|
|
192
184
|
cell_y=self.radius * 2.0,
|
|
193
185
|
cell_z=self.radius * 2.0,
|
|
194
|
-
pos=(0.0, 0.0, 0.0) + particle_grid_offset,
|
|
186
|
+
pos=wp.vec3(0.0, 0.0, 0.0) + particle_grid_offset,
|
|
195
187
|
rot=wp.quat_identity(),
|
|
196
|
-
vel=(0.0, 0.0, 0.0),
|
|
188
|
+
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
197
189
|
mass=grid_cell_volume / PARTICLES_PER_CELL_DIM**3,
|
|
198
190
|
jitter=self.radius * 1.0,
|
|
199
191
|
radius_mean=self.radius,
|
|
200
192
|
)
|
|
201
193
|
|
|
202
|
-
self.grid = Grid3D(vec3i(grid_res), grid_lo, grid_hi)
|
|
194
|
+
self.grid = fem.Grid3D(wp.vec3i(grid_res), grid_lo, grid_hi)
|
|
203
195
|
|
|
204
196
|
# Function spaces
|
|
205
|
-
self.velocity_space = make_polynomial_space(self.grid, dtype=wp.vec3, degree=1)
|
|
206
|
-
self.fraction_space = make_polynomial_space(self.grid, dtype=float, degree=1)
|
|
207
|
-
self.strain_space = make_polynomial_space(
|
|
197
|
+
self.velocity_space = fem.make_polynomial_space(self.grid, dtype=wp.vec3, degree=1)
|
|
198
|
+
self.fraction_space = fem.make_polynomial_space(self.grid, dtype=float, degree=1)
|
|
199
|
+
self.strain_space = fem.make_polynomial_space(
|
|
208
200
|
self.grid,
|
|
209
201
|
dtype=float,
|
|
210
202
|
degree=0,
|
|
@@ -214,29 +206,39 @@ class Example:
|
|
|
214
206
|
self.velocity_field = self.velocity_space.make_field()
|
|
215
207
|
|
|
216
208
|
# Test and trial functions
|
|
217
|
-
self.domain = Cells(self.grid)
|
|
218
|
-
self.velocity_test = make_test(self.velocity_space, domain=self.domain)
|
|
219
|
-
self.velocity_trial = make_trial(self.velocity_space, domain=self.domain)
|
|
220
|
-
self.fraction_test = make_test(self.fraction_space, domain=self.domain)
|
|
221
|
-
self.strain_test = make_test(self.strain_space, domain=self.domain)
|
|
222
|
-
self.strain_trial = make_trial(self.strain_space, domain=self.domain)
|
|
209
|
+
self.domain = fem.Cells(self.grid)
|
|
210
|
+
self.velocity_test = fem.make_test(self.velocity_space, domain=self.domain)
|
|
211
|
+
self.velocity_trial = fem.make_trial(self.velocity_space, domain=self.domain)
|
|
212
|
+
self.fraction_test = fem.make_test(self.fraction_space, domain=self.domain)
|
|
213
|
+
self.strain_test = fem.make_test(self.strain_space, domain=self.domain)
|
|
214
|
+
self.strain_trial = fem.make_trial(self.strain_space, domain=self.domain)
|
|
223
215
|
|
|
224
216
|
# Enforcing the Dirichlet boundary condition the hard way;
|
|
225
217
|
# build projector for velocity left- and right-hand-sides
|
|
226
|
-
boundary = BoundarySides(self.grid)
|
|
227
|
-
u_bd_test = make_test(space=self.velocity_space, domain=boundary)
|
|
228
|
-
u_bd_trial = make_trial(space=self.velocity_space, domain=boundary)
|
|
229
|
-
u_bd_projector = integrate(
|
|
218
|
+
boundary = fem.BoundarySides(self.grid)
|
|
219
|
+
u_bd_test = fem.make_test(space=self.velocity_space, domain=boundary)
|
|
220
|
+
u_bd_trial = fem.make_trial(space=self.velocity_space, domain=boundary)
|
|
221
|
+
u_bd_projector = fem.integrate(
|
|
230
222
|
velocity_boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True, output_dtype=float
|
|
231
223
|
)
|
|
232
224
|
|
|
233
|
-
normalize_dirichlet_projector(u_bd_projector)
|
|
225
|
+
fem.normalize_dirichlet_projector(u_bd_projector)
|
|
234
226
|
self.vel_bd_projector = u_bd_projector
|
|
235
227
|
|
|
228
|
+
# Storage for temporary variables
|
|
229
|
+
self.temporary_store = fem.TemporaryStore()
|
|
230
|
+
|
|
231
|
+
self._divergence_matrix = bsr_zeros(
|
|
232
|
+
self.strain_space.node_count(),
|
|
233
|
+
self.velocity_space.node_count(),
|
|
234
|
+
block_type=wp.mat(shape=(1, 3), dtype=float),
|
|
235
|
+
)
|
|
236
|
+
|
|
236
237
|
# Warp.sim model
|
|
237
238
|
self.model: Model = builder.finalize()
|
|
238
239
|
|
|
239
|
-
|
|
240
|
+
if not self._quiet:
|
|
241
|
+
print("Particle count:", self.model.particle_count)
|
|
240
242
|
|
|
241
243
|
self.state_0: State = self.model.state()
|
|
242
244
|
self.state_0.particle_qd_grad = wp.zeros(shape=(self.model.particle_count), dtype=wp.mat33)
|
|
@@ -244,28 +246,41 @@ class Example:
|
|
|
244
246
|
self.state_1: State = self.model.state()
|
|
245
247
|
self.state_1.particle_qd_grad = wp.zeros(shape=(self.model.particle_count), dtype=wp.mat33)
|
|
246
248
|
|
|
247
|
-
self.renderer =
|
|
249
|
+
self.renderer = warp.sim.render.SimRenderer(self.model, stage, scaling=20.0)
|
|
248
250
|
|
|
249
|
-
def update(self
|
|
250
|
-
|
|
251
|
+
def update(self):
|
|
252
|
+
fem.set_default_temporary_store(self.temporary_store)
|
|
253
|
+
|
|
254
|
+
self.current_frame = self.current_frame + 1
|
|
255
|
+
with wp.ScopedTimer(f"simulate frame {self.current_frame}", active=True):
|
|
251
256
|
for s in range(self.sim_substeps):
|
|
252
257
|
# Bin particles to grid cells
|
|
253
|
-
pic = PicQuadrature(
|
|
254
|
-
domain=Cells(self.grid), positions=self.state_0.particle_q, measures=self.model.particle_mass
|
|
258
|
+
pic = fem.PicQuadrature(
|
|
259
|
+
domain=fem.Cells(self.grid), positions=self.state_0.particle_q, measures=self.model.particle_mass
|
|
255
260
|
)
|
|
256
261
|
|
|
262
|
+
# Borrow some temporary arrays for storing integration results
|
|
263
|
+
inv_volume_temporary = fem.borrow_temporary(
|
|
264
|
+
self.temporary_store, shape=(self.fraction_space.node_count()), dtype=float
|
|
265
|
+
)
|
|
266
|
+
velocity_int_temporary = fem.borrow_temporary(
|
|
267
|
+
self.temporary_store, shape=(self.velocity_space.node_count()), dtype=wp.vec3
|
|
268
|
+
)
|
|
269
|
+
inv_volume = inv_volume_temporary.array
|
|
270
|
+
velocity_int = velocity_int_temporary.array
|
|
271
|
+
|
|
257
272
|
# Inverse volume fraction
|
|
258
|
-
|
|
259
|
-
inv_volume = integrate(
|
|
273
|
+
fem.integrate(
|
|
260
274
|
integrate_fraction,
|
|
261
275
|
quadrature=pic,
|
|
262
|
-
fields={"phi": fraction_test},
|
|
276
|
+
fields={"phi": self.fraction_test},
|
|
263
277
|
accumulate_dtype=float,
|
|
278
|
+
output=inv_volume,
|
|
264
279
|
)
|
|
265
280
|
wp.launch(kernel=invert_volume_kernel, dim=inv_volume.shape, inputs=[inv_volume])
|
|
266
281
|
|
|
267
282
|
# Velocity right-hand side
|
|
268
|
-
|
|
283
|
+
fem.integrate(
|
|
269
284
|
integrate_velocity,
|
|
270
285
|
quadrature=pic,
|
|
271
286
|
fields={"u": self.velocity_test},
|
|
@@ -276,7 +291,7 @@ class Example:
|
|
|
276
291
|
"gravity": self.model.gravity,
|
|
277
292
|
},
|
|
278
293
|
accumulate_dtype=float,
|
|
279
|
-
|
|
294
|
+
output=velocity_int,
|
|
280
295
|
)
|
|
281
296
|
|
|
282
297
|
# Compute constraint-free velocity
|
|
@@ -292,28 +307,29 @@ class Example:
|
|
|
292
307
|
bsr_mv(A=self.vel_bd_projector, x=velocity_int, y=self.velocity_field.dof_values, alpha=-1.0, beta=1.0)
|
|
293
308
|
|
|
294
309
|
# Divergence matrix
|
|
295
|
-
|
|
310
|
+
fem.integrate(
|
|
296
311
|
divergence_form,
|
|
297
312
|
quadrature=pic,
|
|
298
313
|
fields={"u": self.velocity_trial, "psi": self.strain_test},
|
|
299
314
|
accumulate_dtype=float,
|
|
300
|
-
|
|
315
|
+
output=self._divergence_matrix,
|
|
301
316
|
)
|
|
302
317
|
|
|
303
318
|
# Project matrix to enforce boundary conditions
|
|
304
|
-
divergence_mat_tmp = bsr_copy(
|
|
305
|
-
bsr_mm(alpha=-1.0, x=divergence_mat_tmp, y=self.vel_bd_projector, z=
|
|
319
|
+
divergence_mat_tmp = bsr_copy(self._divergence_matrix)
|
|
320
|
+
bsr_mm(alpha=-1.0, x=divergence_mat_tmp, y=self.vel_bd_projector, z=self._divergence_matrix, beta=1.0)
|
|
306
321
|
|
|
307
322
|
# Solve unilateral incompressibility
|
|
308
323
|
solve_incompressibility(
|
|
309
|
-
|
|
324
|
+
self._divergence_matrix,
|
|
310
325
|
inv_volume,
|
|
311
326
|
self.pressure_field.dof_values,
|
|
312
327
|
self.velocity_field.dof_values,
|
|
328
|
+
quiet=self._quiet,
|
|
313
329
|
)
|
|
314
330
|
|
|
315
331
|
# (A)PIC advection
|
|
316
|
-
|
|
332
|
+
fem.interpolate(
|
|
317
333
|
update_particles,
|
|
318
334
|
quadrature=pic,
|
|
319
335
|
values={
|
|
@@ -328,17 +344,17 @@ class Example:
|
|
|
328
344
|
|
|
329
345
|
# swap states
|
|
330
346
|
(self.state_0, self.state_1) = (self.state_1, self.state_0)
|
|
347
|
+
|
|
348
|
+
fem.set_default_temporary_store(None)
|
|
331
349
|
|
|
332
350
|
def render(self, is_live=False):
|
|
333
351
|
with wp.ScopedTimer("render", active=True):
|
|
334
|
-
time =
|
|
352
|
+
time = self.current_frame * self.frame_dt
|
|
335
353
|
|
|
336
354
|
self.renderer.begin_frame(time)
|
|
337
355
|
self.renderer.render(self.state_0)
|
|
338
356
|
self.renderer.end_frame()
|
|
339
357
|
|
|
340
|
-
self.sim_time += self.frame_dt
|
|
341
|
-
|
|
342
358
|
|
|
343
359
|
if __name__ == "__main__":
|
|
344
360
|
wp.set_module_options({"enable_backward": False})
|
|
@@ -348,8 +364,8 @@ if __name__ == "__main__":
|
|
|
348
364
|
|
|
349
365
|
example = Example(stage_path)
|
|
350
366
|
|
|
351
|
-
for i in range(example.
|
|
352
|
-
example.update(
|
|
367
|
+
for i in range(example.num_frames):
|
|
368
|
+
example.update()
|
|
353
369
|
example.render()
|
|
354
370
|
|
|
355
371
|
example.renderer.save()
|
|
@@ -7,28 +7,25 @@ This example simulates a convection-diffusion PDE using semi-Lagrangian advectio
|
|
|
7
7
|
|
|
8
8
|
import argparse
|
|
9
9
|
|
|
10
|
-
import warp as wp
|
|
11
|
-
|
|
12
|
-
from warp.fem.types import *
|
|
13
|
-
from warp.fem.geometry import Grid2D, Trimesh2D
|
|
14
|
-
from warp.fem.field import make_test, make_trial
|
|
15
|
-
from warp.fem.space import make_polynomial_space
|
|
16
|
-
from warp.fem.domain import Cells
|
|
17
|
-
from warp.fem.integrate import integrate, interpolate
|
|
18
|
-
from warp.fem.operator import grad, integrand, lookup
|
|
19
|
-
|
|
20
|
-
from bsr_utils import bsr_to_scipy
|
|
21
|
-
from plot_utils import plot_surface
|
|
22
|
-
from mesh_utils import gen_trimesh
|
|
23
|
-
|
|
24
|
-
from scipy.sparse.linalg import factorized
|
|
25
|
-
|
|
26
|
-
import matplotlib.pyplot as plt
|
|
27
|
-
import matplotlib.animation as animation
|
|
28
|
-
|
|
29
10
|
|
|
30
|
-
|
|
31
|
-
|
|
11
|
+
import warp as wp
|
|
12
|
+
import warp.fem as fem
|
|
13
|
+
|
|
14
|
+
# Import example utilities
|
|
15
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
16
|
+
try:
|
|
17
|
+
from .bsr_utils import bsr_cg
|
|
18
|
+
from .mesh_utils import gen_trimesh
|
|
19
|
+
from .plot_utils import Plot
|
|
20
|
+
except ImportError:
|
|
21
|
+
from bsr_utils import bsr_cg
|
|
22
|
+
from mesh_utils import gen_trimesh
|
|
23
|
+
from plot_utils import Plot
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@fem.integrand
|
|
27
|
+
def initial_condition(domain: fem.Domain, s: fem.Sample):
|
|
28
|
+
"""Initial condition: 1.0 in ]0.6, 0.4[ x ]0.2, 0.8[, 0.0 elsewhere"""
|
|
32
29
|
pos = domain(s)
|
|
33
30
|
if pos[0] > 0.4 and pos[0] < 0.6 and pos[1] > 0.2 and pos[1] < 0.8:
|
|
34
31
|
return 1.0
|
|
@@ -42,13 +39,15 @@ def velocity(pos: wp.vec2, ang_vel: float):
|
|
|
42
39
|
return wp.vec2(offset[1], -offset[0]) * ang_vel
|
|
43
40
|
|
|
44
41
|
|
|
45
|
-
@integrand
|
|
46
|
-
def inertia_form(s: Sample, phi: Field, psi: Field, dt: float):
|
|
42
|
+
@fem.integrand
|
|
43
|
+
def inertia_form(s: fem.Sample, phi: fem.Field, psi: fem.Field, dt: float):
|
|
47
44
|
return phi(s) * psi(s) / dt
|
|
48
45
|
|
|
49
46
|
|
|
50
|
-
@integrand
|
|
51
|
-
def transported_inertia_form(
|
|
47
|
+
@fem.integrand
|
|
48
|
+
def transported_inertia_form(
|
|
49
|
+
s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float, dt: float
|
|
50
|
+
):
|
|
52
51
|
pos = domain(s)
|
|
53
52
|
vel = velocity(pos, ang_vel)
|
|
54
53
|
|
|
@@ -56,100 +55,105 @@ def transported_inertia_form(s: Sample, domain: Domain, phi: Field, psi: Field,
|
|
|
56
55
|
conv_pos = pos - vel * dt
|
|
57
56
|
# lookup opertor constructs a Sample from a world position.
|
|
58
57
|
# the optional last argument provides a initial guess for the lookup
|
|
59
|
-
conv_phi = phi(lookup(domain, conv_pos, s))
|
|
58
|
+
conv_phi = phi(fem.lookup(domain, conv_pos, s))
|
|
60
59
|
|
|
61
60
|
return conv_phi * psi(s) / dt
|
|
62
61
|
|
|
63
62
|
|
|
64
|
-
@integrand
|
|
63
|
+
@fem.integrand
|
|
65
64
|
def diffusion_form(
|
|
66
|
-
s: Sample,
|
|
67
|
-
u: Field,
|
|
68
|
-
v: Field,
|
|
65
|
+
s: fem.Sample,
|
|
66
|
+
u: fem.Field,
|
|
67
|
+
v: fem.Field,
|
|
69
68
|
):
|
|
70
69
|
return wp.dot(
|
|
71
|
-
grad(u, s),
|
|
72
|
-
grad(v, s),
|
|
70
|
+
fem.grad(u, s),
|
|
71
|
+
fem.grad(v, s),
|
|
73
72
|
)
|
|
74
73
|
|
|
75
74
|
|
|
76
|
-
@integrand
|
|
77
|
-
def diffusion_and_inertia_form(s: Sample, phi: Field, psi: Field, dt: float, nu: float):
|
|
75
|
+
@fem.integrand
|
|
76
|
+
def diffusion_and_inertia_form(s: fem.Sample, phi: fem.Field, psi: fem.Field, dt: float, nu: float):
|
|
78
77
|
return inertia_form(s, phi, psi, dt) + nu * diffusion_form(s, phi, psi)
|
|
79
78
|
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
wp.init()
|
|
83
|
-
wp.set_module_options({"enable_backward": False})
|
|
84
|
-
|
|
80
|
+
class Example:
|
|
85
81
|
parser = argparse.ArgumentParser()
|
|
86
82
|
parser.add_argument("--resolution", type=int, default=50)
|
|
87
83
|
parser.add_argument("--degree", type=int, default=2)
|
|
88
|
-
parser.add_argument("--
|
|
84
|
+
parser.add_argument("--num_frames", type=int, default=250)
|
|
89
85
|
parser.add_argument("--viscosity", type=float, default=0.001)
|
|
90
86
|
parser.add_argument("--ang_vel", type=float, default=1.0)
|
|
91
87
|
parser.add_argument("--tri_mesh", action="store_true", help="Use a triangular mesh")
|
|
92
|
-
args = parser.parse_args()
|
|
93
|
-
|
|
94
|
-
res = args.resolution
|
|
95
|
-
dt = 1.0 / (args.ang_vel * res)
|
|
96
|
-
|
|
97
|
-
if args.tri_mesh:
|
|
98
|
-
positions, tri_vidx = gen_trimesh(res=vec2i(res))
|
|
99
|
-
geo = Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
100
|
-
else:
|
|
101
|
-
geo = Grid2D(res=vec2i(res))
|
|
102
|
-
|
|
103
|
-
domain = Cells(geometry=geo)
|
|
104
|
-
scalar_space = make_polynomial_space(geo, degree=args.degree)
|
|
105
|
-
quadrature = None
|
|
106
|
-
|
|
107
|
-
# Initial condition
|
|
108
|
-
phi0 = scalar_space.make_field()
|
|
109
|
-
interpolate(initial_condition, dest=phi0)
|
|
110
|
-
|
|
111
|
-
# Assemble and factorize diffusion and inertia matrix
|
|
112
|
-
test = make_test(space=scalar_space, domain=domain)
|
|
113
|
-
trial = make_trial(space=scalar_space, domain=domain)
|
|
114
|
-
matrix = integrate(
|
|
115
|
-
diffusion_and_inertia_form,
|
|
116
|
-
quadrature=quadrature,
|
|
117
|
-
fields={"phi": trial, "psi": test},
|
|
118
|
-
values={"nu": args.viscosity, "dt": dt},
|
|
119
|
-
)
|
|
120
|
-
matrix_solve = factorized(bsr_to_scipy(matrix))
|
|
121
88
|
|
|
122
|
-
|
|
123
|
-
|
|
89
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
90
|
+
if args is None:
|
|
91
|
+
# Read args from kwargs, add default arg values from parser
|
|
92
|
+
args = argparse.Namespace(**kwargs)
|
|
93
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
94
|
+
self._args = args
|
|
95
|
+
self._quiet = quiet
|
|
96
|
+
|
|
97
|
+
res = args.resolution
|
|
98
|
+
self.sim_dt = 1.0 / (args.ang_vel * res)
|
|
99
|
+
self.current_frame = 0
|
|
100
|
+
|
|
101
|
+
if args.tri_mesh:
|
|
102
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(res))
|
|
103
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
104
|
+
else:
|
|
105
|
+
geo = fem.Grid2D(res=wp.vec2i(res))
|
|
106
|
+
|
|
107
|
+
domain = fem.Cells(geometry=geo)
|
|
108
|
+
scalar_space = fem.make_polynomial_space(geo, degree=args.degree)
|
|
109
|
+
|
|
110
|
+
# Initial condition
|
|
111
|
+
self._phi_field = scalar_space.make_field()
|
|
112
|
+
fem.interpolate(initial_condition, dest=self._phi_field)
|
|
113
|
+
|
|
114
|
+
# Assemble diffusion and inertia matrix
|
|
115
|
+
self._test = fem.make_test(space=scalar_space, domain=domain)
|
|
116
|
+
self._trial = fem.make_trial(space=scalar_space, domain=domain)
|
|
117
|
+
self._matrix = fem.integrate(
|
|
118
|
+
diffusion_and_inertia_form,
|
|
119
|
+
fields={"phi": self._trial, "psi": self._test},
|
|
120
|
+
values={"nu": args.viscosity, "dt": self.sim_dt},
|
|
121
|
+
output_dtype=float,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
self.renderer = Plot(stage)
|
|
125
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
126
|
+
|
|
127
|
+
def update(self):
|
|
128
|
+
self.current_frame += 1
|
|
124
129
|
|
|
125
|
-
for k in range(args.n_frames):
|
|
126
130
|
# right-hand-side -- advected inertia
|
|
127
|
-
rhs = integrate(
|
|
131
|
+
rhs = fem.integrate(
|
|
128
132
|
transported_inertia_form,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
133
|
+
fields={"phi": self._phi_field, "psi": self._test},
|
|
134
|
+
values={"ang_vel": self._args.ang_vel, "dt": self.sim_dt},
|
|
135
|
+
output_dtype=float,
|
|
132
136
|
)
|
|
133
137
|
|
|
134
|
-
# Solve
|
|
135
|
-
x =
|
|
138
|
+
# Solve linear system
|
|
139
|
+
bsr_cg(self._matrix, x=self._phi_field.dof_values, b=rhs, quiet=self._quiet, tol=1.0e-12)
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
def render(self):
|
|
142
|
+
self.renderer.begin_frame(time = self.current_frame * self.sim_dt)
|
|
143
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
144
|
+
self.renderer.end_frame()
|
|
139
145
|
|
|
140
|
-
colormesh = plot_surface(phi0)
|
|
141
|
-
ax = colormesh.axes
|
|
142
146
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return plot_surface(phik, axes=ax)
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
wp.init()
|
|
149
|
+
wp.set_module_options({"enable_backward": False})
|
|
147
150
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
args = Example.parser.parse_args()
|
|
152
|
+
|
|
153
|
+
example = Example(args=args)
|
|
154
|
+
for k in range(args.num_frames):
|
|
155
|
+
print(f"Frame {k}:")
|
|
156
|
+
example.update()
|
|
157
|
+
example.render()
|
|
158
|
+
|
|
159
|
+
example.renderer.plot()
|