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.

Files changed (170) hide show
  1. warp/__init__.py +8 -0
  2. warp/bin/warp-clang.so +0 -0
  3. warp/bin/warp.so +0 -0
  4. warp/build.py +7 -6
  5. warp/build_dll.py +70 -79
  6. warp/builtins.py +10 -6
  7. warp/codegen.py +51 -19
  8. warp/config.py +7 -8
  9. warp/constants.py +3 -0
  10. warp/context.py +948 -245
  11. warp/dlpack.py +198 -113
  12. warp/examples/assets/bunny.usd +0 -0
  13. warp/examples/assets/cartpole.urdf +110 -0
  14. warp/examples/assets/crazyflie.usd +0 -0
  15. warp/examples/assets/cube.usda +42 -0
  16. warp/examples/assets/nv_ant.xml +92 -0
  17. warp/examples/assets/nv_humanoid.xml +183 -0
  18. warp/examples/assets/quadruped.urdf +268 -0
  19. warp/examples/assets/rocks.nvdb +0 -0
  20. warp/examples/assets/rocks.usd +0 -0
  21. warp/examples/assets/sphere.usda +56 -0
  22. warp/examples/assets/torus.usda +105 -0
  23. warp/examples/benchmarks/benchmark_api.py +383 -0
  24. warp/examples/benchmarks/benchmark_cloth.py +279 -0
  25. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
  26. warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
  27. warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
  28. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
  29. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
  30. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
  31. warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
  32. warp/examples/benchmarks/benchmark_launches.py +295 -0
  33. warp/examples/core/example_dem.py +221 -0
  34. warp/examples/core/example_fluid.py +267 -0
  35. warp/examples/core/example_graph_capture.py +129 -0
  36. warp/examples/core/example_marching_cubes.py +177 -0
  37. warp/examples/core/example_mesh.py +154 -0
  38. warp/examples/core/example_mesh_intersect.py +193 -0
  39. warp/examples/core/example_nvdb.py +169 -0
  40. warp/examples/core/example_raycast.py +89 -0
  41. warp/examples/core/example_raymarch.py +178 -0
  42. warp/examples/core/example_render_opengl.py +141 -0
  43. warp/examples/core/example_sph.py +389 -0
  44. warp/examples/core/example_torch.py +181 -0
  45. warp/examples/core/example_wave.py +249 -0
  46. warp/examples/fem/bsr_utils.py +380 -0
  47. warp/examples/fem/example_apic_fluid.py +391 -0
  48. warp/examples/fem/example_convection_diffusion.py +168 -0
  49. warp/examples/fem/example_convection_diffusion_dg.py +209 -0
  50. warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
  51. warp/examples/fem/example_deformed_geometry.py +159 -0
  52. warp/examples/fem/example_diffusion.py +173 -0
  53. warp/examples/fem/example_diffusion_3d.py +152 -0
  54. warp/examples/fem/example_diffusion_mgpu.py +214 -0
  55. warp/examples/fem/example_mixed_elasticity.py +222 -0
  56. warp/examples/fem/example_navier_stokes.py +243 -0
  57. warp/examples/fem/example_stokes.py +192 -0
  58. warp/examples/fem/example_stokes_transfer.py +249 -0
  59. warp/examples/fem/mesh_utils.py +109 -0
  60. warp/examples/fem/plot_utils.py +287 -0
  61. warp/examples/optim/example_bounce.py +248 -0
  62. warp/examples/optim/example_cloth_throw.py +210 -0
  63. warp/examples/optim/example_diffray.py +535 -0
  64. warp/examples/optim/example_drone.py +850 -0
  65. warp/examples/optim/example_inverse_kinematics.py +169 -0
  66. warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
  67. warp/examples/optim/example_spring_cage.py +234 -0
  68. warp/examples/optim/example_trajectory.py +201 -0
  69. warp/examples/sim/example_cartpole.py +128 -0
  70. warp/examples/sim/example_cloth.py +184 -0
  71. warp/examples/sim/example_granular.py +113 -0
  72. warp/examples/sim/example_granular_collision_sdf.py +185 -0
  73. warp/examples/sim/example_jacobian_ik.py +213 -0
  74. warp/examples/sim/example_particle_chain.py +106 -0
  75. warp/examples/sim/example_quadruped.py +179 -0
  76. warp/examples/sim/example_rigid_chain.py +191 -0
  77. warp/examples/sim/example_rigid_contact.py +176 -0
  78. warp/examples/sim/example_rigid_force.py +126 -0
  79. warp/examples/sim/example_rigid_gyroscopic.py +97 -0
  80. warp/examples/sim/example_rigid_soft_contact.py +124 -0
  81. warp/examples/sim/example_soft_body.py +178 -0
  82. warp/fabric.py +29 -20
  83. warp/fem/cache.py +0 -1
  84. warp/fem/dirichlet.py +0 -2
  85. warp/fem/integrate.py +0 -1
  86. warp/jax.py +45 -0
  87. warp/jax_experimental.py +339 -0
  88. warp/native/builtin.h +12 -0
  89. warp/native/bvh.cu +18 -18
  90. warp/native/clang/clang.cpp +8 -3
  91. warp/native/cuda_util.cpp +94 -5
  92. warp/native/cuda_util.h +35 -6
  93. warp/native/cutlass_gemm.cpp +1 -1
  94. warp/native/cutlass_gemm.cu +4 -1
  95. warp/native/error.cpp +66 -0
  96. warp/native/error.h +27 -0
  97. warp/native/mesh.cu +2 -2
  98. warp/native/reduce.cu +4 -4
  99. warp/native/runlength_encode.cu +2 -2
  100. warp/native/scan.cu +2 -2
  101. warp/native/sparse.cu +0 -1
  102. warp/native/temp_buffer.h +2 -2
  103. warp/native/warp.cpp +95 -60
  104. warp/native/warp.cu +1053 -218
  105. warp/native/warp.h +49 -32
  106. warp/optim/linear.py +33 -16
  107. warp/render/render_opengl.py +202 -101
  108. warp/render/render_usd.py +82 -40
  109. warp/sim/__init__.py +13 -4
  110. warp/sim/articulation.py +4 -5
  111. warp/sim/collide.py +320 -175
  112. warp/sim/import_mjcf.py +25 -30
  113. warp/sim/import_urdf.py +94 -63
  114. warp/sim/import_usd.py +51 -36
  115. warp/sim/inertia.py +3 -2
  116. warp/sim/integrator.py +233 -0
  117. warp/sim/integrator_euler.py +447 -469
  118. warp/sim/integrator_featherstone.py +1991 -0
  119. warp/sim/integrator_xpbd.py +1420 -640
  120. warp/sim/model.py +765 -487
  121. warp/sim/particles.py +2 -1
  122. warp/sim/render.py +35 -13
  123. warp/sim/utils.py +222 -11
  124. warp/stubs.py +8 -0
  125. warp/tape.py +16 -1
  126. warp/tests/aux_test_grad_customs.py +23 -0
  127. warp/tests/test_array.py +190 -1
  128. warp/tests/test_async.py +656 -0
  129. warp/tests/test_bool.py +50 -0
  130. warp/tests/test_dlpack.py +164 -11
  131. warp/tests/test_examples.py +166 -74
  132. warp/tests/test_fem.py +8 -1
  133. warp/tests/test_generics.py +15 -5
  134. warp/tests/test_grad.py +1 -1
  135. warp/tests/test_grad_customs.py +172 -12
  136. warp/tests/test_jax.py +254 -0
  137. warp/tests/test_large.py +29 -6
  138. warp/tests/test_launch.py +25 -0
  139. warp/tests/test_linear_solvers.py +20 -3
  140. warp/tests/test_matmul.py +61 -16
  141. warp/tests/test_matmul_lite.py +13 -13
  142. warp/tests/test_mempool.py +186 -0
  143. warp/tests/test_multigpu.py +3 -0
  144. warp/tests/test_options.py +16 -2
  145. warp/tests/test_peer.py +137 -0
  146. warp/tests/test_print.py +3 -1
  147. warp/tests/test_quat.py +23 -0
  148. warp/tests/test_sim_kinematics.py +97 -0
  149. warp/tests/test_snippet.py +126 -3
  150. warp/tests/test_streams.py +108 -79
  151. warp/tests/test_torch.py +16 -8
  152. warp/tests/test_utils.py +32 -27
  153. warp/tests/test_verify_fp.py +65 -0
  154. warp/tests/test_volume.py +1 -1
  155. warp/tests/unittest_serial.py +2 -0
  156. warp/tests/unittest_suites.py +12 -0
  157. warp/tests/unittest_utils.py +14 -7
  158. warp/thirdparty/unittest_parallel.py +15 -3
  159. warp/torch.py +10 -8
  160. warp/types.py +363 -246
  161. warp/utils.py +143 -19
  162. warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
  163. warp_lang-1.0.0.dist-info/METADATA +394 -0
  164. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
  165. warp/sim/optimizer.py +0 -138
  166. warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
  167. warp_lang-0.11.0.dist-info/METADATA +0 -238
  168. /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
  169. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
  170. {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()