warp-lang 0.11.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__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.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +8 -0
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +7 -6
- warp/build_dll.py +70 -79
- warp/builtins.py +10 -6
- warp/codegen.py +51 -19
- warp/config.py +7 -8
- warp/constants.py +3 -0
- warp/context.py +948 -245
- warp/dlpack.py +198 -113
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cartpole.urdf +110 -0
- warp/examples/assets/crazyflie.usd +0 -0
- warp/examples/assets/cube.usda +42 -0
- warp/examples/assets/nv_ant.xml +92 -0
- warp/examples/assets/nv_humanoid.xml +183 -0
- warp/examples/assets/quadruped.urdf +268 -0
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usda +56 -0
- warp/examples/assets/torus.usda +105 -0
- warp/examples/benchmarks/benchmark_api.py +383 -0
- warp/examples/benchmarks/benchmark_cloth.py +279 -0
- warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
- warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
- warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
- warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
- warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
- warp/examples/benchmarks/benchmark_launches.py +295 -0
- warp/examples/core/example_dem.py +221 -0
- warp/examples/core/example_fluid.py +267 -0
- warp/examples/core/example_graph_capture.py +129 -0
- warp/examples/core/example_marching_cubes.py +177 -0
- warp/examples/core/example_mesh.py +154 -0
- warp/examples/core/example_mesh_intersect.py +193 -0
- warp/examples/core/example_nvdb.py +169 -0
- warp/examples/core/example_raycast.py +89 -0
- warp/examples/core/example_raymarch.py +178 -0
- warp/examples/core/example_render_opengl.py +141 -0
- warp/examples/core/example_sph.py +389 -0
- warp/examples/core/example_torch.py +181 -0
- warp/examples/core/example_wave.py +249 -0
- warp/examples/fem/bsr_utils.py +380 -0
- warp/examples/fem/example_apic_fluid.py +391 -0
- warp/examples/fem/example_convection_diffusion.py +168 -0
- warp/examples/fem/example_convection_diffusion_dg.py +209 -0
- warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
- warp/examples/fem/example_deformed_geometry.py +159 -0
- warp/examples/fem/example_diffusion.py +173 -0
- warp/examples/fem/example_diffusion_3d.py +152 -0
- warp/examples/fem/example_diffusion_mgpu.py +214 -0
- warp/examples/fem/example_mixed_elasticity.py +222 -0
- warp/examples/fem/example_navier_stokes.py +243 -0
- warp/examples/fem/example_stokes.py +192 -0
- warp/examples/fem/example_stokes_transfer.py +249 -0
- warp/examples/fem/mesh_utils.py +109 -0
- warp/examples/fem/plot_utils.py +287 -0
- warp/examples/optim/example_bounce.py +248 -0
- warp/examples/optim/example_cloth_throw.py +210 -0
- warp/examples/optim/example_diffray.py +535 -0
- warp/examples/optim/example_drone.py +850 -0
- warp/examples/optim/example_inverse_kinematics.py +169 -0
- warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
- warp/examples/optim/example_spring_cage.py +234 -0
- warp/examples/optim/example_trajectory.py +201 -0
- warp/examples/sim/example_cartpole.py +128 -0
- warp/examples/sim/example_cloth.py +184 -0
- warp/examples/sim/example_granular.py +113 -0
- warp/examples/sim/example_granular_collision_sdf.py +185 -0
- warp/examples/sim/example_jacobian_ik.py +213 -0
- warp/examples/sim/example_particle_chain.py +106 -0
- warp/examples/sim/example_quadruped.py +179 -0
- warp/examples/sim/example_rigid_chain.py +191 -0
- warp/examples/sim/example_rigid_contact.py +176 -0
- warp/examples/sim/example_rigid_force.py +126 -0
- warp/examples/sim/example_rigid_gyroscopic.py +97 -0
- warp/examples/sim/example_rigid_soft_contact.py +124 -0
- warp/examples/sim/example_soft_body.py +178 -0
- warp/fabric.py +29 -20
- warp/fem/cache.py +0 -1
- warp/fem/dirichlet.py +0 -2
- warp/fem/integrate.py +0 -1
- warp/jax.py +45 -0
- warp/jax_experimental.py +339 -0
- warp/native/builtin.h +12 -0
- warp/native/bvh.cu +18 -18
- warp/native/clang/clang.cpp +8 -3
- warp/native/cuda_util.cpp +94 -5
- warp/native/cuda_util.h +35 -6
- warp/native/cutlass_gemm.cpp +1 -1
- warp/native/cutlass_gemm.cu +4 -1
- warp/native/error.cpp +66 -0
- warp/native/error.h +27 -0
- warp/native/mesh.cu +2 -2
- warp/native/reduce.cu +4 -4
- warp/native/runlength_encode.cu +2 -2
- warp/native/scan.cu +2 -2
- warp/native/sparse.cu +0 -1
- warp/native/temp_buffer.h +2 -2
- warp/native/warp.cpp +95 -60
- warp/native/warp.cu +1053 -218
- warp/native/warp.h +49 -32
- warp/optim/linear.py +33 -16
- warp/render/render_opengl.py +202 -101
- warp/render/render_usd.py +82 -40
- warp/sim/__init__.py +13 -4
- warp/sim/articulation.py +4 -5
- warp/sim/collide.py +320 -175
- warp/sim/import_mjcf.py +25 -30
- warp/sim/import_urdf.py +94 -63
- warp/sim/import_usd.py +51 -36
- warp/sim/inertia.py +3 -2
- warp/sim/integrator.py +233 -0
- warp/sim/integrator_euler.py +447 -469
- warp/sim/integrator_featherstone.py +1991 -0
- warp/sim/integrator_xpbd.py +1420 -640
- warp/sim/model.py +765 -487
- warp/sim/particles.py +2 -1
- warp/sim/render.py +35 -13
- warp/sim/utils.py +222 -11
- warp/stubs.py +8 -0
- warp/tape.py +16 -1
- warp/tests/aux_test_grad_customs.py +23 -0
- warp/tests/test_array.py +190 -1
- warp/tests/test_async.py +656 -0
- warp/tests/test_bool.py +50 -0
- warp/tests/test_dlpack.py +164 -11
- warp/tests/test_examples.py +166 -74
- warp/tests/test_fem.py +8 -1
- warp/tests/test_generics.py +15 -5
- warp/tests/test_grad.py +1 -1
- warp/tests/test_grad_customs.py +172 -12
- warp/tests/test_jax.py +254 -0
- warp/tests/test_large.py +29 -6
- warp/tests/test_launch.py +25 -0
- warp/tests/test_linear_solvers.py +20 -3
- warp/tests/test_matmul.py +61 -16
- warp/tests/test_matmul_lite.py +13 -13
- warp/tests/test_mempool.py +186 -0
- warp/tests/test_multigpu.py +3 -0
- warp/tests/test_options.py +16 -2
- warp/tests/test_peer.py +137 -0
- warp/tests/test_print.py +3 -1
- warp/tests/test_quat.py +23 -0
- warp/tests/test_sim_kinematics.py +97 -0
- warp/tests/test_snippet.py +126 -3
- warp/tests/test_streams.py +108 -79
- warp/tests/test_torch.py +16 -8
- warp/tests/test_utils.py +32 -27
- warp/tests/test_verify_fp.py +65 -0
- warp/tests/test_volume.py +1 -1
- warp/tests/unittest_serial.py +2 -0
- warp/tests/unittest_suites.py +12 -0
- warp/tests/unittest_utils.py +14 -7
- warp/thirdparty/unittest_parallel.py +15 -3
- warp/torch.py +10 -8
- warp/types.py +363 -246
- warp/utils.py +143 -19
- warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
- warp_lang-1.0.0.dist-info/METADATA +394 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
- warp/sim/optimizer.py +0 -138
- warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
- warp_lang-0.11.0.dist-info/METADATA +0 -238
- /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
- {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example Convection Diffusion DG
|
|
10
|
+
#
|
|
11
|
+
# This example simulates a convection-diffusion PDE using Discontinuous
|
|
12
|
+
# Galerkin with upwind transport and Symmetric Interior Penalty
|
|
13
|
+
#
|
|
14
|
+
# D phi / dt - nu d2 phi / dx^2 = 0
|
|
15
|
+
###########################################################################
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
|
|
19
|
+
import warp as wp
|
|
20
|
+
import warp.fem as fem
|
|
21
|
+
|
|
22
|
+
from warp.sparse import bsr_axpy
|
|
23
|
+
|
|
24
|
+
# Import example utilities
|
|
25
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
26
|
+
try:
|
|
27
|
+
from .bsr_utils import bsr_cg
|
|
28
|
+
from .mesh_utils import gen_trimesh, gen_quadmesh
|
|
29
|
+
from .plot_utils import Plot
|
|
30
|
+
from .example_convection_diffusion import (
|
|
31
|
+
initial_condition,
|
|
32
|
+
velocity,
|
|
33
|
+
inertia_form,
|
|
34
|
+
diffusion_form,
|
|
35
|
+
)
|
|
36
|
+
except ImportError:
|
|
37
|
+
from bsr_utils import bsr_cg
|
|
38
|
+
from mesh_utils import gen_trimesh, gen_quadmesh
|
|
39
|
+
from plot_utils import Plot
|
|
40
|
+
from example_convection_diffusion import (
|
|
41
|
+
initial_condition,
|
|
42
|
+
velocity,
|
|
43
|
+
inertia_form,
|
|
44
|
+
diffusion_form,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
wp.init()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Standard transport term, on cells' interior
|
|
51
|
+
@fem.integrand
|
|
52
|
+
def transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
53
|
+
pos = domain(s)
|
|
54
|
+
vel = velocity(pos, ang_vel)
|
|
55
|
+
|
|
56
|
+
return psi(s) * wp.dot(fem.grad(phi, s), vel)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# Upwind flux, on cell sides
|
|
60
|
+
@fem.integrand
|
|
61
|
+
def upwind_transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
62
|
+
pos = domain(s)
|
|
63
|
+
vel = velocity(pos, ang_vel)
|
|
64
|
+
vel_n = wp.dot(vel, fem.normal(domain, s))
|
|
65
|
+
|
|
66
|
+
return fem.jump(phi, s) * (-fem.average(psi, s) * vel_n + 0.5 * fem.jump(psi, s) * wp.abs(vel_n))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Symmetric-Interior-Penalty diffusion term (See Pietro Ern 2012)
|
|
70
|
+
@fem.integrand
|
|
71
|
+
def sip_diffusion_form(
|
|
72
|
+
s: fem.Sample,
|
|
73
|
+
domain: fem.Domain,
|
|
74
|
+
psi: fem.Field,
|
|
75
|
+
phi: fem.Field,
|
|
76
|
+
):
|
|
77
|
+
nor = fem.normal(domain, s)
|
|
78
|
+
penalty = fem.measure_ratio(domain, s) * float(fem.degree(psi) * fem.degree(phi))
|
|
79
|
+
|
|
80
|
+
return penalty * fem.jump(phi, s) * fem.jump(psi, s) - (
|
|
81
|
+
wp.dot(fem.grad_average(phi, s), nor) * fem.jump(psi, s)
|
|
82
|
+
+ wp.dot(fem.grad_average(psi, s), nor) * fem.jump(phi, s)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Example:
|
|
87
|
+
parser = argparse.ArgumentParser()
|
|
88
|
+
parser.add_argument("--resolution", type=int, default=50)
|
|
89
|
+
parser.add_argument("--degree", type=int, default=2)
|
|
90
|
+
parser.add_argument("--num_frames", type=int, default=100)
|
|
91
|
+
parser.add_argument("--viscosity", type=float, default=0.001)
|
|
92
|
+
parser.add_argument("--ang_vel", type=float, default=1.0)
|
|
93
|
+
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
94
|
+
|
|
95
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
96
|
+
if args is None:
|
|
97
|
+
# Read args from kwargs, add default arg values from parser
|
|
98
|
+
args = argparse.Namespace(**kwargs)
|
|
99
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
100
|
+
self._args = args
|
|
101
|
+
self._quiet = quiet
|
|
102
|
+
|
|
103
|
+
res = args.resolution
|
|
104
|
+
self.sim_dt = 1.0 / (args.ang_vel * res)
|
|
105
|
+
self.current_frame = 0
|
|
106
|
+
|
|
107
|
+
if args.mesh == "tri":
|
|
108
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
|
|
109
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
110
|
+
elif args.mesh == "quad":
|
|
111
|
+
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
|
|
112
|
+
geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
113
|
+
else:
|
|
114
|
+
geo = fem.Grid2D(res=wp.vec2i(args.resolution))
|
|
115
|
+
|
|
116
|
+
domain = fem.Cells(geometry=geo)
|
|
117
|
+
sides = fem.Sides(geo)
|
|
118
|
+
scalar_space = fem.make_polynomial_space(
|
|
119
|
+
geo,
|
|
120
|
+
discontinuous=True,
|
|
121
|
+
degree=args.degree,
|
|
122
|
+
family=fem.Polynomial.GAUSS_LEGENDRE,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Assemble transport, diffusion and inertia matrices
|
|
126
|
+
|
|
127
|
+
self._test = fem.make_test(space=scalar_space, domain=domain)
|
|
128
|
+
trial = fem.make_trial(space=scalar_space, domain=domain)
|
|
129
|
+
|
|
130
|
+
matrix_inertia = fem.integrate(
|
|
131
|
+
inertia_form,
|
|
132
|
+
fields={"phi": trial, "psi": self._test},
|
|
133
|
+
values={"dt": self.sim_dt},
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
matrix_transport = fem.integrate(
|
|
137
|
+
transport_form,
|
|
138
|
+
fields={"phi": trial, "psi": self._test},
|
|
139
|
+
values={"ang_vel": args.ang_vel},
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
side_test = fem.make_test(space=scalar_space, domain=sides)
|
|
143
|
+
side_trial = fem.make_trial(space=scalar_space, domain=sides)
|
|
144
|
+
|
|
145
|
+
bsr_axpy(
|
|
146
|
+
fem.integrate(
|
|
147
|
+
upwind_transport_form,
|
|
148
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
149
|
+
values={"ang_vel": args.ang_vel},
|
|
150
|
+
),
|
|
151
|
+
y=matrix_transport,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
matrix_diffusion = fem.integrate(
|
|
155
|
+
diffusion_form,
|
|
156
|
+
fields={"u": trial, "v": self._test},
|
|
157
|
+
)
|
|
158
|
+
bsr_axpy(
|
|
159
|
+
fem.integrate(
|
|
160
|
+
sip_diffusion_form,
|
|
161
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
162
|
+
),
|
|
163
|
+
y=matrix_diffusion,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
self._matrix = matrix_inertia
|
|
167
|
+
bsr_axpy(x=matrix_transport, y=self._matrix)
|
|
168
|
+
bsr_axpy(x=matrix_diffusion, y=self._matrix, alpha=args.viscosity)
|
|
169
|
+
|
|
170
|
+
# Initial condition
|
|
171
|
+
self._phi_field = scalar_space.make_field()
|
|
172
|
+
fem.interpolate(initial_condition, dest=self._phi_field)
|
|
173
|
+
|
|
174
|
+
self.renderer = Plot(stage)
|
|
175
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def step(self):
|
|
179
|
+
self.current_frame += 1
|
|
180
|
+
|
|
181
|
+
rhs = fem.integrate(
|
|
182
|
+
inertia_form,
|
|
183
|
+
fields={"phi": self._phi_field, "psi": self._test},
|
|
184
|
+
values={"dt": self.sim_dt},
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
phi = wp.zeros_like(rhs)
|
|
188
|
+
bsr_cg(self._matrix, b=rhs, x=phi, method='bicgstab', quiet=self._quiet)
|
|
189
|
+
|
|
190
|
+
wp.utils.array_cast(in_array=phi, out_array=self._phi_field.dof_values)
|
|
191
|
+
|
|
192
|
+
def render(self):
|
|
193
|
+
self.renderer.begin_frame(time = self.current_frame * self.sim_dt)
|
|
194
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
195
|
+
self.renderer.end_frame()
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
if __name__ == "__main__":
|
|
199
|
+
wp.set_module_options({"enable_backward": False})
|
|
200
|
+
|
|
201
|
+
args = Example.parser.parse_args()
|
|
202
|
+
|
|
203
|
+
example = Example(args=args)
|
|
204
|
+
for k in range(args.num_frames):
|
|
205
|
+
print(f"Frame {k}:")
|
|
206
|
+
example.step()
|
|
207
|
+
example.render()
|
|
208
|
+
|
|
209
|
+
example.renderer.plot()
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example Convection Diffusion DG0
|
|
10
|
+
#
|
|
11
|
+
# This example simulates a convection-diffusion PDE using
|
|
12
|
+
# FVM with upwind transport
|
|
13
|
+
#
|
|
14
|
+
# D phi / dt + nu Div f = 0
|
|
15
|
+
# f = grad phi
|
|
16
|
+
###########################################################################
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
|
|
20
|
+
import warp as wp
|
|
21
|
+
import warp.fem as fem
|
|
22
|
+
|
|
23
|
+
from warp.sparse import bsr_mm, bsr_axpy, bsr_transposed
|
|
24
|
+
|
|
25
|
+
wp.init()
|
|
26
|
+
|
|
27
|
+
# Import example utilities
|
|
28
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
29
|
+
try:
|
|
30
|
+
from .bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
|
|
31
|
+
from .plot_utils import Plot
|
|
32
|
+
from .mesh_utils import gen_trimesh, gen_quadmesh
|
|
33
|
+
from .example_convection_diffusion import initial_condition, velocity, inertia_form
|
|
34
|
+
except ImportError:
|
|
35
|
+
from bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
|
|
36
|
+
from plot_utils import Plot
|
|
37
|
+
from mesh_utils import gen_trimesh, gen_quadmesh
|
|
38
|
+
from example_convection_diffusion import initial_condition, velocity, inertia_form
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@fem.integrand
|
|
42
|
+
def vel_mass_form(
|
|
43
|
+
s: fem.Sample,
|
|
44
|
+
u: fem.Field,
|
|
45
|
+
v: fem.Field,
|
|
46
|
+
):
|
|
47
|
+
return wp.dot(v(s), u(s))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@fem.integrand
|
|
51
|
+
def half_diffusion_form(
|
|
52
|
+
s: fem.Sample,
|
|
53
|
+
domain: fem.Domain,
|
|
54
|
+
psi: fem.Field,
|
|
55
|
+
u: fem.Field,
|
|
56
|
+
):
|
|
57
|
+
return fem.jump(psi, s) * wp.dot(fem.average(u, s), fem.normal(domain, s))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@fem.integrand
|
|
61
|
+
def upwind_transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
62
|
+
pos = domain(s)
|
|
63
|
+
|
|
64
|
+
vel = velocity(pos, ang_vel)
|
|
65
|
+
|
|
66
|
+
vel_n = wp.dot(vel, fem.normal(domain, s))
|
|
67
|
+
|
|
68
|
+
return fem.jump(psi, s) * (fem.average(phi, s) * vel_n + 0.5 * fem.jump(phi, s) * wp.abs(vel_n))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class Example:
|
|
72
|
+
parser = argparse.ArgumentParser()
|
|
73
|
+
parser.add_argument("--resolution", type=int, default=50)
|
|
74
|
+
parser.add_argument("--num_frames", type=int, default=250)
|
|
75
|
+
parser.add_argument("--viscosity", type=float, default=0.001)
|
|
76
|
+
parser.add_argument("--ang_vel", type=float, default=1.0)
|
|
77
|
+
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
78
|
+
|
|
79
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
80
|
+
if args is None:
|
|
81
|
+
# Read args from kwargs, add default arg values from parser
|
|
82
|
+
args = argparse.Namespace(**kwargs)
|
|
83
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
84
|
+
self._args = args
|
|
85
|
+
self._quiet = quiet
|
|
86
|
+
|
|
87
|
+
res = args.resolution
|
|
88
|
+
self.sim_dt = 1.0 / (args.ang_vel * res)
|
|
89
|
+
self.current_frame = 0
|
|
90
|
+
|
|
91
|
+
if args.mesh == "tri":
|
|
92
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
|
|
93
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
94
|
+
elif args.mesh == "quad":
|
|
95
|
+
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
|
|
96
|
+
geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
97
|
+
else:
|
|
98
|
+
geo = fem.Grid2D(res=wp.vec2i(args.resolution))
|
|
99
|
+
|
|
100
|
+
domain = fem.Cells(geometry=geo)
|
|
101
|
+
sides = fem.Sides(geo)
|
|
102
|
+
scalar_space = fem.make_polynomial_space(geo, degree=0)
|
|
103
|
+
|
|
104
|
+
# Inertia matrix
|
|
105
|
+
self._test = fem.make_test(space=scalar_space, domain=domain)
|
|
106
|
+
trial = fem.make_trial(space=scalar_space, domain=domain)
|
|
107
|
+
matrix_inertia = fem.integrate(
|
|
108
|
+
inertia_form,
|
|
109
|
+
fields={"phi": trial, "psi": self._test},
|
|
110
|
+
values={"dt": self.sim_dt},
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Upwind transport term
|
|
114
|
+
side_test = fem.make_test(space=scalar_space, domain=sides)
|
|
115
|
+
side_trial = fem.make_trial(space=scalar_space, domain=sides)
|
|
116
|
+
matrix_transport = fem.integrate(
|
|
117
|
+
upwind_transport_form,
|
|
118
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
119
|
+
values={"ang_vel": args.ang_vel},
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Diffusion bilinear form
|
|
123
|
+
# Since we have piecewise constant element, we cannot use the classical diffusion form
|
|
124
|
+
# Instead we assemble the matrix B M^-1 B^T, with B associated to the form psi div(u)
|
|
125
|
+
# and the diagonal matrix M to the velocity mass form u.v
|
|
126
|
+
|
|
127
|
+
velocity_space = fem.make_polynomial_space(geo, degree=0, dtype=wp.vec2)
|
|
128
|
+
side_trial_vel = fem.make_trial(space=velocity_space, domain=sides)
|
|
129
|
+
matrix_half_diffusion = fem.integrate(
|
|
130
|
+
half_diffusion_form,
|
|
131
|
+
fields={"psi": side_test, "u": side_trial_vel},
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Diagonal velocity mass matrix
|
|
135
|
+
test_vel = fem.make_test(space=velocity_space, domain=domain)
|
|
136
|
+
trial_vel = fem.make_trial(space=velocity_space, domain=domain)
|
|
137
|
+
inv_vel_mass_matrix = fem.integrate(
|
|
138
|
+
vel_mass_form, domain=domain, fields={"u": trial_vel, "v": test_vel}, nodal=True
|
|
139
|
+
)
|
|
140
|
+
invert_diagonal_bsr_mass_matrix(inv_vel_mass_matrix)
|
|
141
|
+
|
|
142
|
+
# Assemble system matrix
|
|
143
|
+
|
|
144
|
+
self._matrix = matrix_inertia
|
|
145
|
+
# matrix += matrix_transport
|
|
146
|
+
bsr_axpy(x=matrix_transport, y=self._matrix)
|
|
147
|
+
# matrix += nu * B M^-1 B^T
|
|
148
|
+
bsr_mm(
|
|
149
|
+
x=bsr_mm(matrix_half_diffusion, inv_vel_mass_matrix),
|
|
150
|
+
y=bsr_transposed(matrix_half_diffusion),
|
|
151
|
+
z=self._matrix,
|
|
152
|
+
alpha=args.viscosity,
|
|
153
|
+
beta=1.0,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Initial condition
|
|
157
|
+
self._phi_field = scalar_space.make_field()
|
|
158
|
+
fem.interpolate(initial_condition, dest=self._phi_field)
|
|
159
|
+
|
|
160
|
+
self.renderer = Plot(stage)
|
|
161
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
162
|
+
|
|
163
|
+
def step(self):
|
|
164
|
+
self.current_frame += 1
|
|
165
|
+
|
|
166
|
+
rhs = fem.integrate(
|
|
167
|
+
inertia_form,
|
|
168
|
+
fields={"phi": self._phi_field, "psi": self._test},
|
|
169
|
+
values={"dt": self.sim_dt},
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
phi = wp.zeros_like(rhs)
|
|
173
|
+
bsr_cg(self._matrix, b=rhs, x=phi, method='bicgstab', quiet=self._quiet)
|
|
174
|
+
|
|
175
|
+
wp.utils.array_cast(in_array=phi, out_array=self._phi_field.dof_values)
|
|
176
|
+
|
|
177
|
+
def render(self):
|
|
178
|
+
self.renderer.begin_frame(time=self.current_frame * self.sim_dt)
|
|
179
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
180
|
+
self.renderer.end_frame()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
wp.set_module_options({"enable_backward": False})
|
|
185
|
+
|
|
186
|
+
args = Example.parser.parse_args()
|
|
187
|
+
|
|
188
|
+
example = Example(args=args)
|
|
189
|
+
for k in range(args.num_frames):
|
|
190
|
+
print(f"Frame {k}:")
|
|
191
|
+
example.step()
|
|
192
|
+
example.render()
|
|
193
|
+
|
|
194
|
+
example.renderer.plot()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example Deformed Geometry
|
|
10
|
+
#
|
|
11
|
+
# This example solves a 2d diffusion problem:
|
|
12
|
+
#
|
|
13
|
+
# nu Div u = 1
|
|
14
|
+
#
|
|
15
|
+
# with Dirichlet boundary conditions on vertical edges and
|
|
16
|
+
# homogeneous Neumann on horizontal edges.
|
|
17
|
+
###########################################################################
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
|
|
21
|
+
import warp as wp
|
|
22
|
+
import warp.fem as fem
|
|
23
|
+
|
|
24
|
+
from warp.sparse import bsr_axpy
|
|
25
|
+
from warp.fem.utils import array_axpy
|
|
26
|
+
|
|
27
|
+
# Import example utilities
|
|
28
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
29
|
+
try:
|
|
30
|
+
from .example_diffusion import linear_form, diffusion_form
|
|
31
|
+
from .bsr_utils import bsr_cg
|
|
32
|
+
from .mesh_utils import gen_trimesh, gen_quadmesh
|
|
33
|
+
from .plot_utils import Plot
|
|
34
|
+
except ImportError:
|
|
35
|
+
from example_diffusion import linear_form, diffusion_form
|
|
36
|
+
from bsr_utils import bsr_cg
|
|
37
|
+
from mesh_utils import gen_trimesh, gen_quadmesh
|
|
38
|
+
from plot_utils import Plot
|
|
39
|
+
|
|
40
|
+
wp.init()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@fem.integrand
|
|
44
|
+
def deformation_field_expr(
|
|
45
|
+
s: fem.Sample,
|
|
46
|
+
domain: fem.Domain,
|
|
47
|
+
):
|
|
48
|
+
"""
|
|
49
|
+
Deformation field mapping the unique square to a circular band
|
|
50
|
+
"""
|
|
51
|
+
x = domain(s)
|
|
52
|
+
|
|
53
|
+
r = x[1] + 0.5
|
|
54
|
+
t = 0.5 * 3.1416 * x[0]
|
|
55
|
+
|
|
56
|
+
return r * wp.vec2(wp.sin(t), wp.cos(t)) - x
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@fem.integrand
|
|
60
|
+
def boundary_projector_form(
|
|
61
|
+
s: fem.Sample,
|
|
62
|
+
domain: fem.Domain,
|
|
63
|
+
u: fem.Field,
|
|
64
|
+
v: fem.Field,
|
|
65
|
+
):
|
|
66
|
+
"""
|
|
67
|
+
Bilinear boundary condition projector form, non-zero on radial edges
|
|
68
|
+
"""
|
|
69
|
+
nor = fem.normal(domain, s)
|
|
70
|
+
active = wp.select(nor[0] < -0.9999 or nor[1] < -0.9999, 0.0, 1.0)
|
|
71
|
+
return active * u(s) * v(s)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Example:
|
|
75
|
+
parser = argparse.ArgumentParser()
|
|
76
|
+
parser.add_argument("--resolution", type=int, default=50)
|
|
77
|
+
parser.add_argument("--degree", type=int, default=2)
|
|
78
|
+
parser.add_argument("--serendipity", action="store_true", default=False)
|
|
79
|
+
parser.add_argument("--viscosity", type=float, default=2.0)
|
|
80
|
+
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
81
|
+
|
|
82
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
83
|
+
if args is None:
|
|
84
|
+
# Read args from kwargs, add default arg values from parser
|
|
85
|
+
args = argparse.Namespace(**kwargs)
|
|
86
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
87
|
+
self._args = args
|
|
88
|
+
self._quiet = quiet
|
|
89
|
+
|
|
90
|
+
# Grid or triangle mesh geometry
|
|
91
|
+
if args.mesh == "tri":
|
|
92
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
|
|
93
|
+
base_geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
94
|
+
elif args.mesh == "quad":
|
|
95
|
+
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
|
|
96
|
+
base_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
97
|
+
else:
|
|
98
|
+
base_geo = fem.Grid2D(res=wp.vec2i(args.resolution))
|
|
99
|
+
|
|
100
|
+
# Construct deformation field on base geometry
|
|
101
|
+
deformation_space = fem.make_polynomial_space(base_geo, degree=args.degree, dtype=wp.vec2)
|
|
102
|
+
deformation_field = deformation_space.make_field()
|
|
103
|
+
fem.interpolate(deformation_field_expr, dest=deformation_field)
|
|
104
|
+
|
|
105
|
+
self._geo = deformation_field.make_deformed_geometry()
|
|
106
|
+
|
|
107
|
+
# Scalar function space on deformed geometry
|
|
108
|
+
element_basis = fem.ElementBasis.SERENDIPITY if args.serendipity else None
|
|
109
|
+
self._scalar_space = fem.make_polynomial_space(self._geo, degree=args.degree, element_basis=element_basis)
|
|
110
|
+
|
|
111
|
+
# Scalar field over our function space
|
|
112
|
+
self._scalar_field = self._scalar_space.make_field()
|
|
113
|
+
|
|
114
|
+
self.renderer = Plot(stage)
|
|
115
|
+
|
|
116
|
+
def step(self):
|
|
117
|
+
args = self._args
|
|
118
|
+
geo = self._geo
|
|
119
|
+
|
|
120
|
+
domain = fem.Cells(geometry=geo)
|
|
121
|
+
|
|
122
|
+
# Right-hand-side (forcing term)
|
|
123
|
+
test = fem.make_test(space=self._scalar_space, domain=domain)
|
|
124
|
+
rhs = fem.integrate(linear_form, fields={"v": test})
|
|
125
|
+
|
|
126
|
+
# Diffusion form
|
|
127
|
+
trial = fem.make_trial(space=self._scalar_space, domain=domain)
|
|
128
|
+
matrix = fem.integrate(diffusion_form, fields={"u": trial, "v": test}, values={"nu": args.viscosity})
|
|
129
|
+
|
|
130
|
+
# Weakly-imposed boundary conditions on all sides
|
|
131
|
+
boundary = fem.BoundarySides(geo)
|
|
132
|
+
bd_test = fem.make_test(space=self._scalar_space, domain=boundary)
|
|
133
|
+
bd_trial = fem.make_trial(space=self._scalar_space, domain=boundary)
|
|
134
|
+
|
|
135
|
+
bd_matrix = fem.integrate(boundary_projector_form, fields={"u": bd_trial, "v": bd_test}, nodal=True)
|
|
136
|
+
|
|
137
|
+
fem.project_linear_system(matrix, rhs, bd_matrix)
|
|
138
|
+
|
|
139
|
+
# Solve linear system using Conjugate Gradient
|
|
140
|
+
x = wp.zeros_like(rhs)
|
|
141
|
+
bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet, tol=1.0e-6)
|
|
142
|
+
|
|
143
|
+
# Assign system result to our discrete field
|
|
144
|
+
self._scalar_field.dof_values = x
|
|
145
|
+
|
|
146
|
+
def render(self):
|
|
147
|
+
self.renderer.add_surface("solution", self._scalar_field)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
wp.set_module_options({"enable_backward": False})
|
|
152
|
+
|
|
153
|
+
args = Example.parser.parse_args()
|
|
154
|
+
|
|
155
|
+
example = Example(args=args)
|
|
156
|
+
example.step()
|
|
157
|
+
example.render()
|
|
158
|
+
|
|
159
|
+
example.renderer.plot()
|