warp-lang 1.0.0b2__py3-none-win_amd64.whl → 1.0.0b6__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (271) hide show
  1. docs/conf.py +17 -5
  2. examples/env/env_ant.py +1 -1
  3. examples/env/env_cartpole.py +1 -1
  4. examples/env/env_humanoid.py +1 -1
  5. examples/env/env_usd.py +4 -1
  6. examples/env/environment.py +8 -9
  7. examples/example_dem.py +34 -33
  8. examples/example_diffray.py +364 -337
  9. examples/example_fluid.py +32 -23
  10. examples/example_jacobian_ik.py +97 -93
  11. examples/example_marching_cubes.py +6 -16
  12. examples/example_mesh.py +6 -16
  13. examples/example_mesh_intersect.py +16 -14
  14. examples/example_nvdb.py +14 -16
  15. examples/example_raycast.py +14 -13
  16. examples/example_raymarch.py +16 -23
  17. examples/example_render_opengl.py +19 -10
  18. examples/example_sim_cartpole.py +82 -78
  19. examples/example_sim_cloth.py +45 -48
  20. examples/example_sim_fk_grad.py +51 -44
  21. examples/example_sim_fk_grad_torch.py +47 -40
  22. examples/example_sim_grad_bounce.py +108 -133
  23. examples/example_sim_grad_cloth.py +99 -113
  24. examples/example_sim_granular.py +5 -6
  25. examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
  26. examples/example_sim_neo_hookean.py +51 -55
  27. examples/example_sim_particle_chain.py +4 -4
  28. examples/example_sim_quadruped.py +126 -81
  29. examples/example_sim_rigid_chain.py +54 -61
  30. examples/example_sim_rigid_contact.py +66 -70
  31. examples/example_sim_rigid_fem.py +3 -3
  32. examples/example_sim_rigid_force.py +1 -1
  33. examples/example_sim_rigid_gyroscopic.py +3 -4
  34. examples/example_sim_rigid_kinematics.py +28 -39
  35. examples/example_sim_trajopt.py +112 -110
  36. examples/example_sph.py +9 -8
  37. examples/example_wave.py +7 -7
  38. examples/fem/bsr_utils.py +30 -17
  39. examples/fem/example_apic_fluid.py +85 -69
  40. examples/fem/example_convection_diffusion.py +97 -93
  41. examples/fem/example_convection_diffusion_dg.py +142 -149
  42. examples/fem/example_convection_diffusion_dg0.py +141 -136
  43. examples/fem/example_deformed_geometry.py +146 -0
  44. examples/fem/example_diffusion.py +115 -84
  45. examples/fem/example_diffusion_3d.py +116 -86
  46. examples/fem/example_diffusion_mgpu.py +102 -79
  47. examples/fem/example_mixed_elasticity.py +139 -100
  48. examples/fem/example_navier_stokes.py +175 -162
  49. examples/fem/example_stokes.py +143 -111
  50. examples/fem/example_stokes_transfer.py +186 -157
  51. examples/fem/mesh_utils.py +59 -97
  52. examples/fem/plot_utils.py +138 -17
  53. tools/ci/publishing/build_nodes_info.py +54 -0
  54. warp/__init__.py +4 -3
  55. warp/__init__.pyi +1 -0
  56. warp/bin/warp-clang.dll +0 -0
  57. warp/bin/warp.dll +0 -0
  58. warp/build.py +5 -3
  59. warp/build_dll.py +29 -9
  60. warp/builtins.py +836 -492
  61. warp/codegen.py +864 -553
  62. warp/config.py +3 -1
  63. warp/context.py +389 -172
  64. warp/fem/__init__.py +24 -6
  65. warp/fem/cache.py +318 -25
  66. warp/fem/dirichlet.py +7 -3
  67. warp/fem/domain.py +14 -0
  68. warp/fem/field/__init__.py +30 -38
  69. warp/fem/field/field.py +149 -0
  70. warp/fem/field/nodal_field.py +244 -138
  71. warp/fem/field/restriction.py +8 -6
  72. warp/fem/field/test.py +127 -59
  73. warp/fem/field/trial.py +117 -60
  74. warp/fem/geometry/__init__.py +5 -1
  75. warp/fem/geometry/deformed_geometry.py +271 -0
  76. warp/fem/geometry/element.py +24 -1
  77. warp/fem/geometry/geometry.py +86 -14
  78. warp/fem/geometry/grid_2d.py +112 -54
  79. warp/fem/geometry/grid_3d.py +134 -65
  80. warp/fem/geometry/hexmesh.py +953 -0
  81. warp/fem/geometry/partition.py +85 -33
  82. warp/fem/geometry/quadmesh_2d.py +532 -0
  83. warp/fem/geometry/tetmesh.py +451 -115
  84. warp/fem/geometry/trimesh_2d.py +197 -92
  85. warp/fem/integrate.py +534 -268
  86. warp/fem/operator.py +58 -31
  87. warp/fem/polynomial.py +11 -0
  88. warp/fem/quadrature/__init__.py +1 -1
  89. warp/fem/quadrature/pic_quadrature.py +150 -58
  90. warp/fem/quadrature/quadrature.py +209 -57
  91. warp/fem/space/__init__.py +230 -53
  92. warp/fem/space/basis_space.py +489 -0
  93. warp/fem/space/collocated_function_space.py +105 -0
  94. warp/fem/space/dof_mapper.py +49 -2
  95. warp/fem/space/function_space.py +90 -39
  96. warp/fem/space/grid_2d_function_space.py +149 -496
  97. warp/fem/space/grid_3d_function_space.py +173 -538
  98. warp/fem/space/hexmesh_function_space.py +352 -0
  99. warp/fem/space/partition.py +129 -76
  100. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  101. warp/fem/space/restriction.py +46 -34
  102. warp/fem/space/shape/__init__.py +15 -0
  103. warp/fem/space/shape/cube_shape_function.py +738 -0
  104. warp/fem/space/shape/shape_function.py +103 -0
  105. warp/fem/space/shape/square_shape_function.py +611 -0
  106. warp/fem/space/shape/tet_shape_function.py +567 -0
  107. warp/fem/space/shape/triangle_shape_function.py +429 -0
  108. warp/fem/space/tetmesh_function_space.py +132 -1039
  109. warp/fem/space/topology.py +295 -0
  110. warp/fem/space/trimesh_2d_function_space.py +104 -742
  111. warp/fem/types.py +13 -11
  112. warp/fem/utils.py +335 -60
  113. warp/native/array.h +120 -34
  114. warp/native/builtin.h +101 -72
  115. warp/native/bvh.cpp +73 -325
  116. warp/native/bvh.cu +406 -23
  117. warp/native/bvh.h +22 -40
  118. warp/native/clang/clang.cpp +1 -0
  119. warp/native/crt.h +2 -0
  120. warp/native/cuda_util.cpp +8 -3
  121. warp/native/cuda_util.h +1 -0
  122. warp/native/exports.h +1522 -1243
  123. warp/native/intersect.h +19 -4
  124. warp/native/intersect_adj.h +8 -8
  125. warp/native/mat.h +76 -17
  126. warp/native/mesh.cpp +33 -108
  127. warp/native/mesh.cu +114 -18
  128. warp/native/mesh.h +395 -40
  129. warp/native/noise.h +272 -329
  130. warp/native/quat.h +51 -8
  131. warp/native/rand.h +44 -34
  132. warp/native/reduce.cpp +1 -1
  133. warp/native/sparse.cpp +4 -4
  134. warp/native/sparse.cu +163 -155
  135. warp/native/spatial.h +2 -2
  136. warp/native/temp_buffer.h +18 -14
  137. warp/native/vec.h +103 -21
  138. warp/native/warp.cpp +2 -1
  139. warp/native/warp.cu +28 -3
  140. warp/native/warp.h +4 -3
  141. warp/render/render_opengl.py +261 -109
  142. warp/sim/__init__.py +1 -2
  143. warp/sim/articulation.py +385 -185
  144. warp/sim/import_mjcf.py +59 -48
  145. warp/sim/import_urdf.py +15 -15
  146. warp/sim/import_usd.py +174 -102
  147. warp/sim/inertia.py +17 -18
  148. warp/sim/integrator_xpbd.py +4 -3
  149. warp/sim/model.py +330 -250
  150. warp/sim/render.py +1 -1
  151. warp/sparse.py +625 -152
  152. warp/stubs.py +341 -309
  153. warp/tape.py +9 -6
  154. warp/tests/__main__.py +3 -6
  155. warp/tests/assets/curlnoise_golden.npy +0 -0
  156. warp/tests/assets/pnoise_golden.npy +0 -0
  157. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  158. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  159. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  160. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  161. warp/tests/aux_test_unresolved_func.py +14 -0
  162. warp/tests/aux_test_unresolved_symbol.py +14 -0
  163. warp/tests/disabled_kinematics.py +239 -0
  164. warp/tests/run_coverage_serial.py +31 -0
  165. warp/tests/test_adam.py +103 -106
  166. warp/tests/test_arithmetic.py +94 -74
  167. warp/tests/test_array.py +82 -101
  168. warp/tests/test_array_reduce.py +57 -23
  169. warp/tests/test_atomic.py +64 -28
  170. warp/tests/test_bool.py +22 -12
  171. warp/tests/test_builtins_resolution.py +1292 -0
  172. warp/tests/test_bvh.py +18 -18
  173. warp/tests/test_closest_point_edge_edge.py +54 -57
  174. warp/tests/test_codegen.py +165 -134
  175. warp/tests/test_compile_consts.py +28 -20
  176. warp/tests/test_conditional.py +108 -24
  177. warp/tests/test_copy.py +10 -12
  178. warp/tests/test_ctypes.py +112 -88
  179. warp/tests/test_dense.py +21 -14
  180. warp/tests/test_devices.py +98 -0
  181. warp/tests/test_dlpack.py +75 -75
  182. warp/tests/test_examples.py +237 -0
  183. warp/tests/test_fabricarray.py +22 -24
  184. warp/tests/test_fast_math.py +15 -11
  185. warp/tests/test_fem.py +1034 -124
  186. warp/tests/test_fp16.py +23 -16
  187. warp/tests/test_func.py +187 -86
  188. warp/tests/test_generics.py +194 -49
  189. warp/tests/test_grad.py +123 -181
  190. warp/tests/test_grad_customs.py +176 -0
  191. warp/tests/test_hash_grid.py +35 -34
  192. warp/tests/test_import.py +10 -23
  193. warp/tests/test_indexedarray.py +24 -25
  194. warp/tests/test_intersect.py +18 -9
  195. warp/tests/test_large.py +141 -0
  196. warp/tests/test_launch.py +14 -41
  197. warp/tests/test_lerp.py +64 -65
  198. warp/tests/test_lvalue.py +493 -0
  199. warp/tests/test_marching_cubes.py +12 -13
  200. warp/tests/test_mat.py +517 -2898
  201. warp/tests/test_mat_lite.py +115 -0
  202. warp/tests/test_mat_scalar_ops.py +2889 -0
  203. warp/tests/test_math.py +103 -9
  204. warp/tests/test_matmul.py +304 -69
  205. warp/tests/test_matmul_lite.py +410 -0
  206. warp/tests/test_mesh.py +60 -22
  207. warp/tests/test_mesh_query_aabb.py +21 -25
  208. warp/tests/test_mesh_query_point.py +111 -22
  209. warp/tests/test_mesh_query_ray.py +12 -24
  210. warp/tests/test_mlp.py +30 -22
  211. warp/tests/test_model.py +92 -89
  212. warp/tests/test_modules_lite.py +39 -0
  213. warp/tests/test_multigpu.py +88 -114
  214. warp/tests/test_noise.py +12 -11
  215. warp/tests/test_operators.py +16 -20
  216. warp/tests/test_options.py +11 -11
  217. warp/tests/test_pinned.py +17 -18
  218. warp/tests/test_print.py +32 -11
  219. warp/tests/test_quat.py +275 -129
  220. warp/tests/test_rand.py +18 -16
  221. warp/tests/test_reload.py +38 -34
  222. warp/tests/test_rounding.py +50 -43
  223. warp/tests/test_runlength_encode.py +168 -20
  224. warp/tests/test_smoothstep.py +9 -11
  225. warp/tests/test_snippet.py +143 -0
  226. warp/tests/test_sparse.py +261 -63
  227. warp/tests/test_spatial.py +276 -243
  228. warp/tests/test_streams.py +110 -85
  229. warp/tests/test_struct.py +268 -63
  230. warp/tests/test_tape.py +39 -21
  231. warp/tests/test_torch.py +90 -86
  232. warp/tests/test_transient_module.py +10 -12
  233. warp/tests/test_types.py +363 -0
  234. warp/tests/test_utils.py +451 -0
  235. warp/tests/test_vec.py +354 -2050
  236. warp/tests/test_vec_lite.py +73 -0
  237. warp/tests/test_vec_scalar_ops.py +2099 -0
  238. warp/tests/test_volume.py +418 -376
  239. warp/tests/test_volume_write.py +124 -134
  240. warp/tests/unittest_serial.py +35 -0
  241. warp/tests/unittest_suites.py +291 -0
  242. warp/tests/unittest_utils.py +342 -0
  243. warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
  244. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  245. warp/thirdparty/appdirs.py +36 -45
  246. warp/thirdparty/unittest_parallel.py +589 -0
  247. warp/types.py +622 -211
  248. warp/utils.py +54 -393
  249. warp_lang-1.0.0b6.dist-info/METADATA +238 -0
  250. warp_lang-1.0.0b6.dist-info/RECORD +409 -0
  251. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
  252. examples/example_cache_management.py +0 -40
  253. examples/example_multigpu.py +0 -54
  254. examples/example_struct.py +0 -65
  255. examples/fem/example_stokes_transfer_3d.py +0 -210
  256. warp/bin/warp-clang.so +0 -0
  257. warp/bin/warp.so +0 -0
  258. warp/fem/field/discrete_field.py +0 -80
  259. warp/fem/space/nodal_function_space.py +0 -233
  260. warp/tests/test_all.py +0 -223
  261. warp/tests/test_array_scan.py +0 -60
  262. warp/tests/test_base.py +0 -208
  263. warp/tests/test_unresolved_func.py +0 -7
  264. warp/tests/test_unresolved_symbol.py +0 -7
  265. warp_lang-1.0.0b2.dist-info/METADATA +0 -26
  266. warp_lang-1.0.0b2.dist-info/RECORD +0 -380
  267. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  268. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  269. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  270. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  271. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
@@ -5,30 +5,27 @@ This example illustrates using domain decomposition to solve a diffusion PDE ove
5
5
  from typing import Tuple
6
6
 
7
7
  import warp as wp
8
-
9
- from warp.fem.types import *
10
- from warp.fem.geometry import Grid2D, LinearGeometryPartition
11
- from warp.fem.space import make_polynomial_space, make_space_partition
12
- from warp.fem.field import make_test, make_trial
13
- from warp.fem.domain import Cells, BoundarySides
14
- from warp.fem.integrate import integrate
15
- from warp.fem.operator import integrand
16
-
8
+ import warp.fem as fem
17
9
  from warp.sparse import bsr_axpy, bsr_mv
18
10
  from warp.utils import array_cast
19
11
 
20
- from example_diffusion import linear_form, diffusion_form
21
- from bsr_utils import bsr_cg
22
- from plot_utils import plot_grid_surface
23
-
24
- import matplotlib.pyplot as plt
12
+ # Import example utilities
13
+ # Make sure that works both when imported as module and run as standalone file
14
+ try:
15
+ from .bsr_utils import bsr_cg
16
+ from .example_diffusion import diffusion_form, linear_form
17
+ from .plot_utils import Plot
18
+ except ImportError:
19
+ from bsr_utils import bsr_cg
20
+ from example_diffusion import diffusion_form, linear_form
21
+ from plot_utils import Plot
25
22
 
26
23
 
27
- @integrand
24
+ @fem.integrand
28
25
  def mass_form(
29
- s: Sample,
30
- u: Field,
31
- v: Field,
26
+ s: fem.Sample,
27
+ u: fem.Field,
28
+ v: fem.Field,
32
29
  ):
33
30
  return u(s) * v(s)
34
31
 
@@ -96,77 +93,103 @@ def mv_routine(A: DistributedSystem, x: wp.array, y: wp.array, alpha=1.0, beta=0
96
93
  wp.launch(kernel=sum_kernel, dim=idx.shape, device=y_idx.device, inputs=[y_idx, tmp_i], stream=stream)
97
94
 
98
95
 
99
- if __name__ == "__main__":
100
- wp.init()
101
- wp.set_module_options({"enable_backward": False})
102
-
103
- geo = Grid2D(res=vec2i(25))
104
- bd_weight = 100.0
105
-
106
- scalar_space = make_polynomial_space(geo, degree=3)
107
-
108
- devices = wp.get_cuda_devices()
109
-
110
- rhs_vecs = []
111
- res_vecs = []
112
- matrices = []
113
- indices = []
114
-
115
- main_device = devices[0]
116
-
117
- # Build local system for each device
118
- for k, device in enumerate(devices):
119
- with wp.ScopedDevice(device):
120
- # Construct the partition corresponding to the k'th device
121
- geo_partition = LinearGeometryPartition(geo, k, len(devices))
122
- space_partition = make_space_partition(scalar_space, geo_partition)
123
-
124
- domain = Cells(geometry=geo_partition)
96
+ class Example:
97
+ def __init__(self, stage=None, quiet=False):
98
+ self._bd_weight = 100.0
99
+ self._quiet = quiet
100
+
101
+ self._geo = fem.Grid2D(res=wp.vec2i(25))
102
+
103
+ self._main_device = wp.get_device("cuda")
104
+
105
+ with wp.ScopedDevice(self._main_device):
106
+ self._scalar_space = fem.make_polynomial_space(self._geo, degree=3)
107
+ self._scalar_field = self._scalar_space.make_field()
108
+
109
+ self.renderer = Plot(stage)
110
+
111
+ def update(self):
112
+ devices = wp.get_cuda_devices()
113
+ main_device = self._main_device
114
+
115
+ rhs_vecs = []
116
+ res_vecs = []
117
+ matrices = []
118
+ indices = []
119
+
120
+ # Build local system for each device
121
+ for k, device in enumerate(devices):
122
+ with wp.ScopedDevice(device):
123
+ # Construct the partition corresponding to the k'th device
124
+ geo_partition = fem.LinearGeometryPartition(self._geo, k, len(devices))
125
+ matrix, rhs, partition_node_indices = self._assemble_local_system(geo_partition)
126
+
127
+ rhs_vecs.append(rhs)
128
+ res_vecs.append(wp.empty_like(rhs))
129
+ matrices.append(matrix)
130
+ indices.append(partition_node_indices.to(main_device))
131
+
132
+ # Global rhs as sum of all local rhs
133
+ glob_rhs = wp.zeros(n=self._scalar_space.node_count(), dtype=wp.float64, device=main_device)
134
+ tmp = wp.empty_like(glob_rhs)
135
+ sum_vecs(rhs_vecs, indices, glob_rhs, tmp)
136
+
137
+ # Distributed CG
138
+ global_res = wp.zeros_like(glob_rhs)
139
+ A = DistributedSystem()
140
+ A.device = device
141
+ A.scalar_type = glob_rhs.dtype
142
+ A.nrow = self._scalar_space.node_count()
143
+ A.shape = (A.nrow, A.nrow)
144
+ A.tmp_buf = tmp
145
+ A.rank_data = (matrices, rhs_vecs, res_vecs, indices)
146
+
147
+ bsr_cg(
148
+ A,
149
+ x=global_res,
150
+ b=glob_rhs,
151
+ use_diag_precond=False,
152
+ quiet=self._quiet,
153
+ mv_routine=mv_routine,
154
+ device=main_device,
155
+ )
125
156
 
126
- # Right-hand-side
127
- test = make_test(space_partition=space_partition, domain=domain)
128
- rhs = integrate(linear_form, fields={"v": test})
157
+ array_cast(in_array=global_res, out_array=self._scalar_field.dof_values)
129
158
 
130
- # Weakly-imposed boundary conditions on all sides
131
- boundary = BoundarySides(geometry=geo_partition)
132
- bd_test = make_test(space_partition=space_partition, domain=boundary)
133
- bd_trial = make_trial(space_partition=space_partition, domain=boundary)
134
- bd_matrix = integrate(mass_form, fields={"u": bd_trial, "v": bd_test})
159
+ def render(self):
160
+ self.renderer.add_surface("solution", self._scalar_field)
135
161
 
136
- # Diffusion form
137
- trial = make_trial(space_partition=space_partition, domain=domain)
138
- matrix = integrate(diffusion_form, fields={"u": trial, "v": test}, values={"nu": 1.0})
162
+ def _assemble_local_system(self, geo_partition: fem.GeometryPartition):
163
+ scalar_space = self._scalar_space
164
+ space_partition = fem.make_space_partition(scalar_space, geo_partition)
139
165
 
140
- bsr_axpy(y=matrix, x=bd_matrix, alpha=bd_weight)
166
+ domain = fem.Cells(geometry=geo_partition)
141
167
 
142
- rhs_vecs.append(rhs)
143
- res_vecs.append(wp.empty_like(rhs))
144
- matrices.append(matrix)
145
- indices.append(space_partition.space_node_indices().to(main_device))
168
+ # Right-hand-side
169
+ test = fem.make_test(space=scalar_space, space_partition=space_partition, domain=domain)
170
+ rhs = fem.integrate(linear_form, fields={"v": test})
146
171
 
172
+ # Weakly-imposed boundary conditions on all sides
173
+ boundary = fem.BoundarySides(geometry=geo_partition)
174
+ bd_test = fem.make_test(space=scalar_space, space_partition=space_partition, domain=boundary)
175
+ bd_trial = fem.make_trial(space=scalar_space, space_partition=space_partition, domain=boundary)
176
+ bd_matrix = fem.integrate(mass_form, fields={"u": bd_trial, "v": bd_test})
147
177
 
148
- # Global rhs as sum of all local rhs
149
- glob_rhs = wp.zeros(n=scalar_space.node_count(), dtype=wp.float64, device=main_device)
150
- tmp = wp.empty_like(glob_rhs)
151
- sum_vecs(rhs_vecs, indices, glob_rhs, tmp)
178
+ # Diffusion form
179
+ trial = fem.make_trial(space=scalar_space, space_partition=space_partition, domain=domain)
180
+ matrix = fem.integrate(diffusion_form, fields={"u": trial, "v": test}, values={"nu": 1.0})
152
181
 
153
- # Distributed CG
154
- glob_res = wp.zeros_like(glob_rhs)
155
- A = DistributedSystem()
156
- A.device = device
157
- A.scalar_type = glob_rhs.dtype
158
- A.nrow = scalar_space.node_count()
159
- A.shape = (A.nrow, A.nrow)
160
- A.tmp_buf = tmp
161
- A.rank_data = (matrices, rhs_vecs, res_vecs, indices)
182
+ bsr_axpy(y=matrix, x=bd_matrix, alpha=self._bd_weight)
162
183
 
163
- with wp.ScopedDevice(main_device):
164
- bsr_cg(A, x=glob_res, b=glob_rhs, use_diag_precond=False, mv_routine=mv_routine, device=main_device)
184
+ return matrix, rhs, space_partition.space_node_indices()
165
185
 
166
- scalar_field = scalar_space.make_field()
167
186
 
168
- array_cast(in_array=glob_res, out_array=scalar_field.dof_values)
187
+ if __name__ == "__main__":
188
+ wp.init()
189
+ wp.set_module_options({"enable_backward": False})
169
190
 
170
- plot_grid_surface(scalar_field)
191
+ example = Example()
192
+ example.update()
193
+ example.render()
171
194
 
172
- plt.show()
195
+ example.renderer.plot()
@@ -5,25 +5,20 @@ with Dirichlet boundary conditions on horizontal sides, and E the elasticity ran
5
5
  import argparse
6
6
 
7
7
  import warp as wp
8
-
9
8
  import numpy as np
10
9
 
11
- from warp.fem.types import *
12
- from warp.fem.geometry import Grid2D, Trimesh2D
13
- from warp.fem.field import make_test, make_trial
14
- from warp.fem.space import make_polynomial_space, SymmetricTensorMapper
15
- from warp.fem.domain import Cells, BoundarySides
16
- from warp.fem.integrate import integrate
17
- from warp.fem.operator import normal, integrand, D
18
- from warp.fem.dirichlet import project_linear_system
10
+ import warp.fem as fem
19
11
 
20
12
  from warp.sparse import bsr_transposed, bsr_mm
21
13
 
22
- from plot_utils import plot_velocities
23
- from bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
24
- from mesh_utils import gen_trimesh
25
-
26
- import matplotlib.pyplot as plt
14
+ try:
15
+ from .plot_utils import Plot
16
+ from .bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
17
+ from .mesh_utils import gen_trimesh, gen_quadmesh
18
+ except ImportError:
19
+ from plot_utils import Plot
20
+ from bsr_utils import bsr_cg, invert_diagonal_bsr_mass_matrix
21
+ from mesh_utils import gen_trimesh, gen_quadmesh
27
22
 
28
23
 
29
24
  @wp.func
@@ -34,134 +29,178 @@ def compute_stress(tau: wp.mat22, E: wp.mat33):
34
29
  return wp.mat22(sig_sym[0], 0.5 * sig_sym[2], 0.5 * sig_sym[2], sig_sym[1])
35
30
 
36
31
 
37
- @integrand
32
+ @fem.integrand
38
33
  def symmetric_grad_form(
39
- s: Sample,
40
- u: Field,
41
- tau: Field,
34
+ s: fem.Sample,
35
+ u: fem.Field,
36
+ tau: fem.Field,
42
37
  ):
43
38
  """D(u) : tau"""
44
- return wp.ddot(tau(s), D(u, s))
39
+ return wp.ddot(tau(s), fem.D(u, s))
45
40
 
46
41
 
47
- @integrand
48
- def stress_form(s: Sample, u: Field, tau: Field, E: wp.mat33):
42
+ @fem.integrand
43
+ def stress_form(s: fem.Sample, u: fem.Field, tau: fem.Field, E: wp.mat33):
49
44
  """(E : D(u)) : tau"""
50
- return wp.ddot(tau(s), compute_stress(D(u, s), E))
45
+ return wp.ddot(tau(s), compute_stress(fem.D(u, s), E))
51
46
 
52
47
 
53
- @integrand
48
+ @fem.integrand
54
49
  def horizontal_boundary_projector_form(
55
- s: Sample,
56
- domain: Domain,
57
- u: Field,
58
- v: Field,
50
+ s: fem.Sample,
51
+ domain: fem.Domain,
52
+ u: fem.Field,
53
+ v: fem.Field,
59
54
  ):
60
55
  # non zero on horizontal boundary of domain only
61
- nor = normal(domain, s)
56
+ nor = fem.normal(domain, s)
62
57
  return wp.dot(u(s), v(s)) * wp.abs(nor[1])
63
58
 
64
59
 
65
- @integrand
60
+ @fem.integrand
66
61
  def horizontal_displacement_form(
67
- s: Sample,
68
- domain: Domain,
69
- v: Field,
62
+ s: fem.Sample,
63
+ domain: fem.Domain,
64
+ v: fem.Field,
70
65
  displacement: float,
71
66
  ):
72
67
  # opposed to normal on horizontal boundary of domain only
73
- nor = normal(domain, s)
68
+ nor = fem.normal(domain, s)
74
69
  return -wp.abs(nor[1]) * displacement * wp.dot(nor, v(s))
75
70
 
76
71
 
77
- @integrand
72
+ @fem.integrand
78
73
  def tensor_mass_form(
79
- s: Sample,
80
- sig: Field,
81
- tau: Field,
74
+ s: fem.Sample,
75
+ sig: fem.Field,
76
+ tau: fem.Field,
82
77
  ):
83
78
  return wp.ddot(tau(s), sig(s))
84
79
 
85
80
 
86
- if __name__ == "__main__":
87
- wp.init()
88
- wp.set_module_options({"enable_backward": False})
89
-
81
+ class Example:
90
82
  parser = argparse.ArgumentParser()
91
83
  parser.add_argument("--resolution", type=int, default=25)
92
84
  parser.add_argument("--degree", type=int, default=2)
93
85
  parser.add_argument("--displacement", type=float, default=0.1)
94
86
  parser.add_argument("--young_modulus", type=float, default=1.0)
95
87
  parser.add_argument("--poisson_ratio", type=float, default=0.5)
96
- parser.add_argument("--tri_mesh", action="store_true", help="Use a triangular mesh")
97
- args = parser.parse_args()
98
-
99
- if args.tri_mesh:
100
- positions, tri_vidx = gen_trimesh(res=vec2i(args.resolution))
101
- geo = Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
102
- else:
103
- geo = Grid2D(res=vec2i(args.resolution))
104
-
105
- boundary = BoundarySides(geo)
106
-
107
- # Strain-stress matrix
108
- young = args.young_modulus
109
- poisson = args.poisson_ratio
110
- elasticity_mat = wp.mat33(
111
- young
112
- / (1.0 - poisson * poisson)
113
- * np.array(
114
- [[1.0, poisson, 0.0], [poisson, 1.0, 0.0], [0.0, 0.0, (2.0 * (1.0 + poisson)) * (1.0 - poisson * poisson)]]
115
- )
88
+ parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
89
+ parser.add_argument(
90
+ "--nonconforming_stresses", action="store_true", help="For grid, use non-conforming stresses (Q_d/P_d)"
116
91
  )
117
92
 
118
- domain = Cells(geometry=geo)
93
+ def __init__(self, stage=None, quiet=False, args=None, **kwargs):
94
+ if args is None:
95
+ # Read args from kwargs, add default arg values from parser
96
+ args = argparse.Namespace(**kwargs)
97
+ args = Example.parser.parse_args(args=[], namespace=args)
98
+ self._args = args
99
+ self._quiet = quiet
100
+
101
+ # Grid or triangle mesh geometry
102
+ if args.mesh == "tri":
103
+ positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
104
+ self._geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
105
+ elif args.mesh == "quad":
106
+ positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
107
+ self._geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
108
+ else:
109
+ self._geo = fem.Grid2D(res=wp.vec2i(args.resolution))
110
+
111
+ # Strain-stress matrix
112
+ young = args.young_modulus
113
+ poisson = args.poisson_ratio
114
+ self._elasticity_mat = wp.mat33(
115
+ young
116
+ / (1.0 - poisson * poisson)
117
+ * np.array(
118
+ [
119
+ [1.0, poisson, 0.0],
120
+ [poisson, 1.0, 0.0],
121
+ [0.0, 0.0, (2.0 * (1.0 + poisson)) * (1.0 - poisson * poisson)],
122
+ ]
123
+ )
124
+ )
119
125
 
120
- # Function spaces -- Q_k for displacement, Q_{k-1}d for stress
121
- u_space = make_polynomial_space(geo, degree=args.degree, dtype=wp.vec2)
122
- # Store stress degrees of freedom as symmetric tensors (3 dof) rather than full 2x2 matrices
123
- tau_space = make_polynomial_space(
124
- geo, degree=args.degree - 1, discontinuous=True, dof_mapper=SymmetricTensorMapper(wp.mat22)
125
- )
126
+ # Function spaces -- S_k for displacement, Q_{k-1}d for stress
127
+ self._u_space = fem.make_polynomial_space(
128
+ self._geo, degree=args.degree, dtype=wp.vec2, element_basis=fem.ElementBasis.SERENDIPITY
129
+ )
126
130
 
127
- # Displacement boundary conditions
128
- u_bd_test = make_test(space=u_space, domain=boundary)
129
- u_bd_trial = make_trial(space=u_space, domain=boundary)
130
- u_bd_rhs = integrate(
131
- horizontal_displacement_form,
132
- fields={"v": u_bd_test},
133
- values={"displacement": args.displacement},
134
- nodal=True,
135
- output_dtype=wp.vec2d,
136
- )
137
- u_bd_matrix = integrate(horizontal_boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True)
131
+ # Store stress degrees of freedom as symmetric tensors (3 dof) rather than full 2x2 matrices
132
+ tau_basis = (
133
+ fem.ElementBasis.NONCONFORMING_POLYNOMIAL if args.nonconforming_stresses else fem.ElementBasis.LAGRANGE
134
+ )
135
+ self._tau_space = fem.make_polynomial_space(
136
+ self._geo,
137
+ degree=args.degree - 1,
138
+ discontinuous=True,
139
+ element_basis=tau_basis,
140
+ dof_mapper=fem.SymmetricTensorMapper(wp.mat22),
141
+ )
138
142
 
139
- # Stress/velocity coupling
140
- u_trial = make_trial(space=u_space, domain=domain)
141
- tau_test = make_test(space=tau_space, domain=domain)
142
- tau_trial = make_trial(space=tau_space, domain=domain)
143
+ self._u_field = self._u_space.make_field()
143
144
 
144
- sym_grad_matrix = integrate(symmetric_grad_form, fields={"u": u_trial, "tau": tau_test})
145
- stress_matrix = integrate(stress_form, fields={"u": u_trial, "tau": tau_test}, values={"E": elasticity_mat})
145
+ self.renderer = Plot(stage)
146
146
 
147
- # Compute inverse of the (block-diagonal) tau mass matrix
148
- tau_inv_mass_matrix = integrate(tensor_mass_form, fields={"sig": tau_trial, "tau": tau_test}, nodal=True)
149
- invert_diagonal_bsr_mass_matrix(tau_inv_mass_matrix)
147
+ def update(self):
148
+ boundary = fem.BoundarySides(self._geo)
149
+ domain = fem.Cells(geometry=self._geo)
150
150
 
151
- # Assemble system matrix
152
- u_matrix = bsr_mm(bsr_transposed(sym_grad_matrix), bsr_mm(tau_inv_mass_matrix, stress_matrix))
151
+ # Displacement boundary conditions
152
+ u_bd_test = fem.make_test(space=self._u_space, domain=boundary)
153
+ u_bd_trial = fem.make_trial(space=self._u_space, domain=boundary)
154
+ u_bd_rhs = fem.integrate(
155
+ horizontal_displacement_form,
156
+ fields={"v": u_bd_test},
157
+ values={"displacement": self._args.displacement},
158
+ nodal=True,
159
+ output_dtype=wp.vec2d,
160
+ )
161
+ u_bd_matrix = fem.integrate(
162
+ horizontal_boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True
163
+ )
164
+
165
+ # Stress/velocity coupling
166
+ u_trial = fem.make_trial(space=self._u_space, domain=domain)
167
+ tau_test = fem.make_test(space=self._tau_space, domain=domain)
168
+ tau_trial = fem.make_trial(space=self._tau_space, domain=domain)
169
+
170
+ sym_grad_matrix = fem.integrate(symmetric_grad_form, fields={"u": u_trial, "tau": tau_test})
171
+ stress_matrix = fem.integrate(
172
+ stress_form, fields={"u": u_trial, "tau": tau_test}, values={"E": self._elasticity_mat}
173
+ )
174
+
175
+ # Compute inverse of the (block-diagonal) tau mass matrix
176
+ tau_inv_mass_matrix = fem.integrate(tensor_mass_form, fields={"sig": tau_trial, "tau": tau_test}, nodal=True)
177
+ invert_diagonal_bsr_mass_matrix(tau_inv_mass_matrix)
178
+
179
+ # Assemble system matrix
180
+ u_matrix = bsr_mm(bsr_transposed(sym_grad_matrix), bsr_mm(tau_inv_mass_matrix, stress_matrix))
181
+
182
+ # Enforce boundary conditions
183
+ u_rhs = wp.zeros_like(u_bd_rhs)
184
+ fem.project_linear_system(u_matrix, u_rhs, u_bd_matrix, u_bd_rhs)
153
185
 
154
- # Enforce boundary conditions
155
- u_rhs = wp.zeros_like(u_bd_rhs)
156
- project_linear_system(u_matrix, u_rhs, u_bd_matrix, u_bd_rhs)
186
+ x = wp.zeros_like(u_rhs)
187
+ bsr_cg(u_matrix, b=u_rhs, x=x, tol=1.0e-16, quiet=self._quiet)
157
188
 
158
- x = wp.zeros_like(u_rhs)
159
- bsr_cg(u_matrix, b=u_rhs, x=x, tol=1.0e-16)
189
+ # Extract result
190
+ self._u_field.dof_values = x
191
+
192
+ def render(self):
193
+ self.renderer.add_surface_vector("solution", self._u_field)
194
+
195
+
196
+ if __name__ == "__main__":
197
+ wp.init()
198
+ wp.set_module_options({"enable_backward": False})
160
199
 
161
- # Extract result
162
- u_field = u_space.make_field()
163
- u_field.dof_values = x # .reshape((-1, 2))
200
+ args = Example.parser.parse_args()
164
201
 
165
- plot_velocities(u_field)
202
+ example = Example(args=args)
203
+ example.update()
204
+ example.render()
166
205
 
167
- plt.show()
206
+ example.renderer.plot()