warp-lang 1.2.1__py3-none-manylinux2014_aarch64.whl → 1.3.0__py3-none-manylinux2014_aarch64.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 (194) hide show
  1. warp/__init__.py +8 -6
  2. warp/autograd.py +823 -0
  3. warp/bin/warp-clang.so +0 -0
  4. warp/bin/warp.so +0 -0
  5. warp/build.py +6 -2
  6. warp/builtins.py +1410 -886
  7. warp/codegen.py +503 -166
  8. warp/config.py +48 -18
  9. warp/context.py +401 -199
  10. warp/dlpack.py +8 -0
  11. warp/examples/assets/bunny.usd +0 -0
  12. warp/examples/benchmarks/benchmark_cloth_warp.py +1 -1
  13. warp/examples/benchmarks/benchmark_interop_torch.py +158 -0
  14. warp/examples/benchmarks/benchmark_launches.py +1 -1
  15. warp/examples/core/example_cupy.py +78 -0
  16. warp/examples/fem/example_apic_fluid.py +17 -36
  17. warp/examples/fem/example_burgers.py +9 -18
  18. warp/examples/fem/example_convection_diffusion.py +7 -17
  19. warp/examples/fem/example_convection_diffusion_dg.py +27 -47
  20. warp/examples/fem/example_deformed_geometry.py +11 -22
  21. warp/examples/fem/example_diffusion.py +7 -18
  22. warp/examples/fem/example_diffusion_3d.py +24 -28
  23. warp/examples/fem/example_diffusion_mgpu.py +7 -14
  24. warp/examples/fem/example_magnetostatics.py +190 -0
  25. warp/examples/fem/example_mixed_elasticity.py +111 -80
  26. warp/examples/fem/example_navier_stokes.py +30 -34
  27. warp/examples/fem/example_nonconforming_contact.py +290 -0
  28. warp/examples/fem/example_stokes.py +17 -32
  29. warp/examples/fem/example_stokes_transfer.py +12 -21
  30. warp/examples/fem/example_streamlines.py +350 -0
  31. warp/examples/fem/utils.py +936 -0
  32. warp/fabric.py +5 -2
  33. warp/fem/__init__.py +13 -3
  34. warp/fem/cache.py +161 -11
  35. warp/fem/dirichlet.py +37 -28
  36. warp/fem/domain.py +105 -14
  37. warp/fem/field/__init__.py +14 -3
  38. warp/fem/field/field.py +454 -11
  39. warp/fem/field/nodal_field.py +33 -18
  40. warp/fem/geometry/deformed_geometry.py +50 -15
  41. warp/fem/geometry/hexmesh.py +12 -24
  42. warp/fem/geometry/nanogrid.py +106 -31
  43. warp/fem/geometry/quadmesh_2d.py +6 -11
  44. warp/fem/geometry/tetmesh.py +103 -61
  45. warp/fem/geometry/trimesh_2d.py +98 -47
  46. warp/fem/integrate.py +231 -186
  47. warp/fem/operator.py +14 -9
  48. warp/fem/quadrature/pic_quadrature.py +35 -9
  49. warp/fem/quadrature/quadrature.py +119 -32
  50. warp/fem/space/basis_space.py +98 -22
  51. warp/fem/space/collocated_function_space.py +3 -1
  52. warp/fem/space/function_space.py +7 -2
  53. warp/fem/space/grid_2d_function_space.py +3 -3
  54. warp/fem/space/grid_3d_function_space.py +4 -4
  55. warp/fem/space/hexmesh_function_space.py +3 -2
  56. warp/fem/space/nanogrid_function_space.py +12 -14
  57. warp/fem/space/partition.py +45 -47
  58. warp/fem/space/restriction.py +19 -16
  59. warp/fem/space/shape/cube_shape_function.py +91 -3
  60. warp/fem/space/shape/shape_function.py +7 -0
  61. warp/fem/space/shape/square_shape_function.py +32 -0
  62. warp/fem/space/shape/tet_shape_function.py +11 -7
  63. warp/fem/space/shape/triangle_shape_function.py +10 -1
  64. warp/fem/space/topology.py +116 -42
  65. warp/fem/types.py +8 -1
  66. warp/fem/utils.py +301 -83
  67. warp/native/array.h +16 -0
  68. warp/native/builtin.h +0 -15
  69. warp/native/cuda_util.cpp +14 -6
  70. warp/native/exports.h +1348 -1308
  71. warp/native/quat.h +79 -0
  72. warp/native/rand.h +27 -4
  73. warp/native/sparse.cpp +83 -81
  74. warp/native/sparse.cu +381 -453
  75. warp/native/vec.h +64 -0
  76. warp/native/volume.cpp +40 -49
  77. warp/native/volume_builder.cu +2 -3
  78. warp/native/volume_builder.h +12 -17
  79. warp/native/warp.cu +3 -3
  80. warp/native/warp.h +69 -59
  81. warp/render/render_opengl.py +17 -9
  82. warp/sim/articulation.py +117 -17
  83. warp/sim/collide.py +35 -29
  84. warp/sim/model.py +123 -18
  85. warp/sim/render.py +3 -1
  86. warp/sparse.py +867 -203
  87. warp/stubs.py +312 -541
  88. warp/tape.py +29 -1
  89. warp/tests/disabled_kinematics.py +1 -1
  90. warp/tests/test_adam.py +1 -1
  91. warp/tests/test_arithmetic.py +1 -1
  92. warp/tests/test_array.py +58 -1
  93. warp/tests/test_array_reduce.py +1 -1
  94. warp/tests/test_async.py +1 -1
  95. warp/tests/test_atomic.py +1 -1
  96. warp/tests/test_bool.py +1 -1
  97. warp/tests/test_builtins_resolution.py +1 -1
  98. warp/tests/test_bvh.py +6 -1
  99. warp/tests/test_closest_point_edge_edge.py +1 -1
  100. warp/tests/test_codegen.py +66 -1
  101. warp/tests/test_compile_consts.py +1 -1
  102. warp/tests/test_conditional.py +1 -1
  103. warp/tests/test_copy.py +1 -1
  104. warp/tests/test_ctypes.py +1 -1
  105. warp/tests/test_dense.py +1 -1
  106. warp/tests/test_devices.py +1 -1
  107. warp/tests/test_dlpack.py +1 -1
  108. warp/tests/test_examples.py +33 -4
  109. warp/tests/test_fabricarray.py +5 -2
  110. warp/tests/test_fast_math.py +1 -1
  111. warp/tests/test_fem.py +213 -6
  112. warp/tests/test_fp16.py +1 -1
  113. warp/tests/test_func.py +1 -1
  114. warp/tests/test_future_annotations.py +90 -0
  115. warp/tests/test_generics.py +1 -1
  116. warp/tests/test_grad.py +1 -1
  117. warp/tests/test_grad_customs.py +1 -1
  118. warp/tests/test_grad_debug.py +247 -0
  119. warp/tests/test_hash_grid.py +6 -1
  120. warp/tests/test_implicit_init.py +354 -0
  121. warp/tests/test_import.py +1 -1
  122. warp/tests/test_indexedarray.py +1 -1
  123. warp/tests/test_intersect.py +1 -1
  124. warp/tests/test_jax.py +1 -1
  125. warp/tests/test_large.py +1 -1
  126. warp/tests/test_launch.py +1 -1
  127. warp/tests/test_lerp.py +1 -1
  128. warp/tests/test_linear_solvers.py +1 -1
  129. warp/tests/test_lvalue.py +1 -1
  130. warp/tests/test_marching_cubes.py +5 -2
  131. warp/tests/test_mat.py +34 -35
  132. warp/tests/test_mat_lite.py +2 -1
  133. warp/tests/test_mat_scalar_ops.py +1 -1
  134. warp/tests/test_math.py +1 -1
  135. warp/tests/test_matmul.py +20 -16
  136. warp/tests/test_matmul_lite.py +1 -1
  137. warp/tests/test_mempool.py +1 -1
  138. warp/tests/test_mesh.py +5 -2
  139. warp/tests/test_mesh_query_aabb.py +1 -1
  140. warp/tests/test_mesh_query_point.py +1 -1
  141. warp/tests/test_mesh_query_ray.py +1 -1
  142. warp/tests/test_mlp.py +1 -1
  143. warp/tests/test_model.py +1 -1
  144. warp/tests/test_module_hashing.py +77 -1
  145. warp/tests/test_modules_lite.py +1 -1
  146. warp/tests/test_multigpu.py +1 -1
  147. warp/tests/test_noise.py +1 -1
  148. warp/tests/test_operators.py +1 -1
  149. warp/tests/test_options.py +1 -1
  150. warp/tests/test_overwrite.py +542 -0
  151. warp/tests/test_peer.py +1 -1
  152. warp/tests/test_pinned.py +1 -1
  153. warp/tests/test_print.py +1 -1
  154. warp/tests/test_quat.py +15 -1
  155. warp/tests/test_rand.py +1 -1
  156. warp/tests/test_reload.py +1 -1
  157. warp/tests/test_rounding.py +1 -1
  158. warp/tests/test_runlength_encode.py +1 -1
  159. warp/tests/test_scalar_ops.py +95 -0
  160. warp/tests/test_sim_grad.py +1 -1
  161. warp/tests/test_sim_kinematics.py +1 -1
  162. warp/tests/test_smoothstep.py +1 -1
  163. warp/tests/test_sparse.py +82 -15
  164. warp/tests/test_spatial.py +1 -1
  165. warp/tests/test_special_values.py +2 -11
  166. warp/tests/test_streams.py +11 -1
  167. warp/tests/test_struct.py +1 -1
  168. warp/tests/test_tape.py +1 -1
  169. warp/tests/test_torch.py +194 -1
  170. warp/tests/test_transient_module.py +1 -1
  171. warp/tests/test_types.py +1 -1
  172. warp/tests/test_utils.py +1 -1
  173. warp/tests/test_vec.py +15 -63
  174. warp/tests/test_vec_lite.py +2 -1
  175. warp/tests/test_vec_scalar_ops.py +122 -39
  176. warp/tests/test_verify_fp.py +1 -1
  177. warp/tests/test_volume.py +28 -2
  178. warp/tests/test_volume_write.py +1 -1
  179. warp/tests/unittest_serial.py +1 -1
  180. warp/tests/unittest_suites.py +9 -1
  181. warp/tests/walkthrough_debug.py +1 -1
  182. warp/thirdparty/unittest_parallel.py +2 -5
  183. warp/torch.py +103 -41
  184. warp/types.py +344 -227
  185. warp/utils.py +11 -2
  186. {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/METADATA +99 -46
  187. warp_lang-1.3.0.dist-info/RECORD +368 -0
  188. warp/examples/fem/bsr_utils.py +0 -378
  189. warp/examples/fem/mesh_utils.py +0 -133
  190. warp/examples/fem/plot_utils.py +0 -292
  191. warp_lang-1.2.1.dist-info/RECORD +0 -359
  192. {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/LICENSE.md +0 -0
  193. {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/WHEEL +0 -0
  194. {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@
8
8
  ###########################################################################
9
9
  # Example Deformed Geometry
10
10
  #
11
- # This example solves a 2d diffusion problem:
11
+ # This example solves a 2d diffusion problem on a deformed (curved) mesh:
12
12
  #
13
13
  # nu Div u = 1
14
14
  #
@@ -17,20 +17,9 @@
17
17
  ###########################################################################
18
18
 
19
19
  import warp as wp
20
+ import warp.examples.fem.utils as fem_example_utils
20
21
  import warp.fem as fem
21
-
22
- # Import example utilities
23
- # Make sure that works both when imported as module and run as standalone file
24
- try:
25
- from .bsr_utils import bsr_cg
26
- from .example_diffusion import diffusion_form, linear_form
27
- from .mesh_utils import gen_quadmesh, gen_trimesh
28
- from .plot_utils import Plot
29
- except ImportError:
30
- from bsr_utils import bsr_cg
31
- from example_diffusion import diffusion_form, linear_form
32
- from mesh_utils import gen_quadmesh, gen_trimesh
33
- from plot_utils import Plot
22
+ from warp.examples.fem.example_diffusion import diffusion_form, linear_form
34
23
 
35
24
 
36
25
  @fem.integrand
@@ -46,7 +35,7 @@ def deformation_field_expr(
46
35
  r = x[1] + 0.5
47
36
  t = 0.5 * 3.1416 * x[0]
48
37
 
49
- return r * wp.vec2(wp.sin(t), wp.cos(t)) - x
38
+ return r * wp.vec2(wp.sin(t), wp.cos(t))
50
39
 
51
40
 
52
41
  @fem.integrand
@@ -80,10 +69,10 @@ class Example:
80
69
 
81
70
  # Grid or triangle mesh geometry
82
71
  if mesh == "tri":
83
- positions, tri_vidx = gen_trimesh(res=wp.vec2i(resolution))
72
+ positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(resolution))
84
73
  base_geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
85
74
  elif mesh == "quad":
86
- positions, quad_vidx = gen_quadmesh(res=wp.vec2i(resolution))
75
+ positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
87
76
  base_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
88
77
  else:
89
78
  base_geo = fem.Grid2D(res=wp.vec2i(resolution))
@@ -93,7 +82,7 @@ class Example:
93
82
  deformation_field = deformation_space.make_field()
94
83
  fem.interpolate(deformation_field_expr, dest=deformation_field)
95
84
 
96
- self._geo = deformation_field.make_deformed_geometry()
85
+ self._geo = deformation_field.make_deformed_geometry(relative=False)
97
86
 
98
87
  # Scalar function space on deformed geometry
99
88
  element_basis = fem.ElementBasis.SERENDIPITY if serendipity else None
@@ -102,7 +91,7 @@ class Example:
102
91
  # Scalar field over our function space
103
92
  self._scalar_field = self._scalar_space.make_field()
104
93
 
105
- self.renderer = Plot()
94
+ self.renderer = fem_example_utils.Plot()
106
95
 
107
96
  def step(self):
108
97
  geo = self._geo
@@ -128,13 +117,13 @@ class Example:
128
117
 
129
118
  # Solve linear system using Conjugate Gradient
130
119
  x = wp.zeros_like(rhs)
131
- bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet, tol=1.0e-6)
120
+ fem_example_utils.bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet, tol=1.0e-6)
132
121
 
133
122
  # Assign system result to our discrete field
134
123
  self._scalar_field.dof_values = x
135
124
 
136
125
  def render(self):
137
- self.renderer.add_surface("solution", self._scalar_field)
126
+ self.renderer.add_field("solution", self._scalar_field)
138
127
 
139
128
 
140
129
  if __name__ == "__main__":
@@ -148,7 +137,7 @@ if __name__ == "__main__":
148
137
  parser.add_argument("--degree", type=int, default=2, help="Polynomial degree of shape functions.")
149
138
  parser.add_argument("--serendipity", action="store_true", default=False, help="Use Serendipity basis functions.")
150
139
  parser.add_argument("--viscosity", type=float, default=2.0, help="Fluid viscosity parameter.")
151
- parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
140
+ parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="tri", help="Mesh type")
152
141
  parser.add_argument(
153
142
  "--headless",
154
143
  action="store_true",
@@ -17,20 +17,9 @@
17
17
  ###########################################################################
18
18
 
19
19
  import warp as wp
20
+ import warp.examples.fem.utils as fem_example_utils
20
21
  import warp.fem as fem
21
22
  from warp.fem.utils import array_axpy
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_quadmesh, gen_trimesh
29
- from .plot_utils import Plot
30
- except ImportError:
31
- from bsr_utils import bsr_cg
32
- from mesh_utils import gen_quadmesh, gen_trimesh
33
- from plot_utils import Plot
34
23
 
35
24
 
36
25
  @fem.integrand
@@ -92,10 +81,10 @@ class Example:
92
81
 
93
82
  # Grid or triangle mesh geometry
94
83
  if mesh == "tri":
95
- positions, tri_vidx = gen_trimesh(res=wp.vec2i(resolution))
84
+ positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(resolution))
96
85
  self._geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
97
86
  elif mesh == "quad":
98
- positions, quad_vidx = gen_quadmesh(res=wp.vec2i(resolution))
87
+ positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
99
88
  self._geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
100
89
  else:
101
90
  self._geo = fem.Grid2D(res=wp.vec2i(resolution))
@@ -107,7 +96,7 @@ class Example:
107
96
  # Scalar field over our function space
108
97
  self._scalar_field = self._scalar_space.make_field()
109
98
 
110
- self.renderer = Plot()
99
+ self.renderer = fem_example_utils.Plot()
111
100
 
112
101
  def step(self):
113
102
  geo = self._geo
@@ -140,18 +129,18 @@ class Example:
140
129
  else:
141
130
  # Weak BC: add together diffusion and boundary condition matrices
142
131
  boundary_strength = 1.0 / self._boundary_compliance
143
- bsr_axpy(x=bd_matrix, y=matrix, alpha=boundary_strength, beta=1)
132
+ matrix += bd_matrix * boundary_strength
144
133
  array_axpy(x=bd_rhs, y=rhs, alpha=boundary_strength, beta=1)
145
134
 
146
135
  # Solve linear system using Conjugate Gradient
147
136
  x = wp.zeros_like(rhs)
148
- bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet)
137
+ fem_example_utils.bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet)
149
138
 
150
139
  # Assign system result to our discrete field
151
140
  self._scalar_field.dof_values = x
152
141
 
153
142
  def render(self):
154
- self.renderer.add_surface("solution", self._scalar_field)
143
+ self.renderer.add_field("solution", self._scalar_field)
155
144
 
156
145
 
157
146
  if __name__ == "__main__":
@@ -17,22 +17,11 @@
17
17
  ###########################################################################
18
18
 
19
19
  import warp as wp
20
+ import warp.examples.fem.utils as fem_example_utils
20
21
  import warp.fem as fem
22
+ from warp.examples.fem.example_diffusion import diffusion_form, linear_form
21
23
  from warp.sparse import bsr_axpy
22
24
 
23
- # Import example utilities
24
- # Make sure that works both when imported as module and run as standalone file
25
- try:
26
- from .bsr_utils import bsr_cg
27
- from .example_diffusion import diffusion_form, linear_form
28
- from .mesh_utils import gen_hexmesh, gen_tetmesh
29
- from .plot_utils import Plot
30
- except ImportError:
31
- from bsr_utils import bsr_cg
32
- from example_diffusion import diffusion_form, linear_form
33
- from mesh_utils import gen_hexmesh, gen_tetmesh
34
- from plot_utils import Plot
35
-
36
25
 
37
26
  @fem.integrand
38
27
  def vert_boundary_projector_form(
@@ -41,8 +30,9 @@ def vert_boundary_projector_form(
41
30
  u: fem.Field,
42
31
  v: fem.Field,
43
32
  ):
44
- # Non-zero mass on vertical sides only
45
- w = 1.0 - wp.abs(fem.normal(domain, s)[1])
33
+ # Constrain XY and YZ faces
34
+ nor = fem.normal(domain, s)
35
+ w = 1.0 - wp.abs(nor[1])
46
36
  return w * u(s) * v(s)
47
37
 
48
38
 
@@ -62,30 +52,36 @@ class Example:
62
52
  self._viscosity = viscosity
63
53
  self._boundary_compliance = boundary_compliance
64
54
 
65
- res = wp.vec3i(resolution, resolution // 2, resolution * 2)
55
+ res = wp.vec3i(resolution, max(1, resolution // 2), resolution * 2)
56
+ bounds_lo = wp.vec3(0.0, 0.0, 0.0)
57
+ bounds_hi = wp.vec3(1.0, 0.5, 2.0)
66
58
 
67
59
  if mesh == "tet":
68
- pos, tet_vtx_indices = gen_tetmesh(
60
+ pos, tet_vtx_indices = fem_example_utils.gen_tetmesh(
69
61
  res=res,
70
- bounds_lo=wp.vec3(0.0, 0.0, 0.0),
71
- bounds_hi=wp.vec3(1.0, 0.5, 2.0),
62
+ bounds_lo=bounds_lo,
63
+ bounds_hi=bounds_hi,
72
64
  )
73
65
  self._geo = fem.Tetmesh(tet_vtx_indices, pos)
74
66
  elif mesh == "hex":
75
- pos, hex_vtx_indices = gen_hexmesh(
67
+ pos, hex_vtx_indices = fem_example_utils.gen_hexmesh(
76
68
  res=res,
77
- bounds_lo=wp.vec3(0.0, 0.0, 0.0),
78
- bounds_hi=wp.vec3(1.0, 0.5, 2.0),
69
+ bounds_lo=bounds_lo,
70
+ bounds_hi=bounds_hi,
79
71
  )
80
72
  self._geo = fem.Hexmesh(hex_vtx_indices, pos)
81
73
  elif mesh == "nano":
82
- volume = wp.Volume.allocate(min=[0, 0, 0], max=[1.0, 0.5, 2.0], voxel_size=1.0 / res[0], bg_value=None)
74
+ volume = fem_example_utils.gen_volume(
75
+ res=res,
76
+ bounds_lo=bounds_lo,
77
+ bounds_hi=bounds_hi,
78
+ )
83
79
  self._geo = fem.Nanogrid(volume)
84
80
  else:
85
81
  self._geo = fem.Grid3D(
86
82
  res=res,
87
- bounds_lo=wp.vec3(0.0, 0.0, 0.0),
88
- bounds_hi=wp.vec3(1.0, 0.5, 2.0),
83
+ bounds_lo=bounds_lo,
84
+ bounds_hi=bounds_hi,
89
85
  )
90
86
 
91
87
  # Domain and function spaces
@@ -95,7 +91,7 @@ class Example:
95
91
  # Scalar field over our function space
96
92
  self._scalar_field: fem.DiscreteField = self._scalar_space.make_field()
97
93
 
98
- self.renderer = Plot()
94
+ self.renderer = fem_example_utils.Plot()
99
95
 
100
96
  def step(self):
101
97
  geo = self._geo
@@ -129,11 +125,11 @@ class Example:
129
125
 
130
126
  with wp.ScopedTimer("CG solve"):
131
127
  x = wp.zeros_like(rhs)
132
- bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet)
128
+ fem_example_utils.bsr_cg(matrix, b=rhs, x=x, quiet=self._quiet)
133
129
  self._scalar_field.dof_values = x
134
130
 
135
131
  def render(self):
136
- self.renderer.add_volume("solution", self._scalar_field)
132
+ self.renderer.add_field("solution", self._scalar_field)
137
133
 
138
134
 
139
135
  if __name__ == "__main__":
@@ -15,21 +15,12 @@
15
15
  from typing import Tuple
16
16
 
17
17
  import warp as wp
18
+ import warp.examples.fem.utils as fem_example_utils
18
19
  import warp.fem as fem
20
+ from warp.examples.fem.example_diffusion import diffusion_form, linear_form
19
21
  from warp.sparse import bsr_axpy, bsr_mv
20
22
  from warp.utils import array_cast
21
23
 
22
- # Import example utilities
23
- # Make sure that works both when imported as module and run as standalone file
24
- try:
25
- from .bsr_utils import bsr_cg
26
- from .example_diffusion import diffusion_form, linear_form
27
- from .plot_utils import Plot
28
- except ImportError:
29
- from bsr_utils import bsr_cg
30
- from example_diffusion import diffusion_form, linear_form
31
- from plot_utils import Plot
32
-
33
24
 
34
25
  @fem.integrand
35
26
  def mass_form(
@@ -115,7 +106,7 @@ class Example:
115
106
  self._scalar_space = fem.make_polynomial_space(self._geo, degree=3)
116
107
  self._scalar_field = self._scalar_space.make_field()
117
108
 
118
- self.renderer = Plot()
109
+ self.renderer = fem_example_utils.Plot()
119
110
 
120
111
  def step(self):
121
112
  devices = wp.get_cuda_devices()
@@ -161,12 +152,14 @@ class Example:
161
152
  A.rank_data = (matrices, rhs_vecs, res_vecs, indices)
162
153
 
163
154
  with wp.ScopedDevice(main_device):
164
- bsr_cg(A, x=global_res, b=glob_rhs, use_diag_precond=False, quiet=self._quiet, mv_routine=A.mv_routine)
155
+ fem_example_utils.bsr_cg(
156
+ A, x=global_res, b=glob_rhs, use_diag_precond=False, quiet=self._quiet, mv_routine=A.mv_routine
157
+ )
165
158
 
166
159
  array_cast(in_array=global_res, out_array=self._scalar_field.dof_values)
167
160
 
168
161
  def render(self):
169
- self.renderer.add_surface("solution", self._scalar_field)
162
+ self.renderer.add_field("solution", self._scalar_field)
170
163
 
171
164
  def _assemble_local_system(self, geo_partition: fem.GeometryPartition):
172
165
  scalar_space = self._scalar_space
@@ -0,0 +1,190 @@
1
+ # Copyright (c) 2024 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 Magnetostatics
10
+ #
11
+ # This example demonstrates solving an in-plane magnetostatics problem
12
+ # using a curl-curl formulation
13
+ #
14
+ # 1/mu Curl B + j = 0
15
+ # Div. B = 0
16
+ #
17
+ # solved over field A such that B = Curl A, A = (0, 0, a_z),
18
+ # and a_z = 0 on the domain boundary
19
+ #
20
+ # This example also illustrates using an ImplictField to warp a square mesh
21
+ # to a circular domain
22
+ ###########################################################################
23
+
24
+ import numpy as np
25
+
26
+ import warp as wp
27
+ import warp.examples.fem.utils as fem_example_utils
28
+ import warp.fem as fem
29
+
30
+ # Vacuum and copper magnetic permeabilities
31
+ MU_0 = wp.constant(np.pi * 4.0e-7)
32
+ MU_C = wp.constant(1.25e-6)
33
+
34
+
35
+ @wp.func
36
+ def square_to_disk(x: wp.vec2):
37
+ # mapping from unit square to unit disk
38
+ return wp.normalize(x) * wp.max(wp.abs(x))
39
+
40
+
41
+ @wp.func
42
+ def square_to_disk_grad(x: wp.vec2):
43
+ # gradient of mapping from unit square to unit disk
44
+ if x == wp.vec2(0.0):
45
+ return wp.mat22(0.0)
46
+
47
+ d = wp.normalize(x)
48
+ d_grad = (wp.identity(n=2, dtype=float) - wp.outer(d, d)) / wp.length(x)
49
+
50
+ ax = wp.abs(x)
51
+ xinf = wp.max(ax)
52
+
53
+ xinf_grad = wp.select(ax[0] > ax[1], wp.vec2(0.0, wp.sign(x[1])), wp.vec(wp.sign(x[0]), 0.0))
54
+
55
+ return d_grad * xinf + wp.outer(d, xinf_grad)
56
+
57
+
58
+ @wp.func
59
+ def permeability_field(pos: wp.vec2, coil_height: float, coil_internal_radius: float, coil_external_radius: float):
60
+ # space-varying permeability
61
+
62
+ x = wp.abs(pos[0])
63
+ y = wp.abs(pos[1])
64
+ return wp.select(
65
+ y < coil_height and x > coil_internal_radius and x < coil_external_radius,
66
+ MU_0,
67
+ MU_C,
68
+ )
69
+
70
+
71
+ @wp.func
72
+ def current_field(
73
+ pos: wp.vec2, coil_height: float, coil_internal_radius: float, coil_external_radius: float, current: float
74
+ ):
75
+ # space-varying current direction along z axis (0, +1 or -1)
76
+ x = wp.abs(pos[0])
77
+ y = wp.abs(pos[1])
78
+ return (
79
+ wp.select(
80
+ y < coil_height and x > coil_internal_radius and x < coil_external_radius,
81
+ 0.0,
82
+ wp.sign(pos[0]),
83
+ )
84
+ * current
85
+ )
86
+
87
+
88
+ @fem.integrand
89
+ def curl_z(u: fem.Field, s: fem.Sample):
90
+ # projection of curl((0, 0, u)) over z axis
91
+ du = fem.grad(u, s)
92
+ return wp.vec2(du[1], -du[0])
93
+
94
+
95
+ @fem.integrand
96
+ def curl_curl_form(s: fem.Sample, domain: fem.Domain, u: fem.Field, v: fem.Field, mu: fem.Field):
97
+ return wp.dot(curl_z(u, s), curl_z(v, s)) / mu(s)
98
+
99
+
100
+ @fem.integrand
101
+ def mass_form(s: fem.Sample, domain: fem.Domain, v: fem.Field, u: fem.Field):
102
+ return u(s) * v(s)
103
+
104
+
105
+ class Example:
106
+ def __init__(self, quiet=False, degree=2, resolution=32, domain_radius=2.0, current=1.0e6):
107
+ # We mesh the unit disk by first meshing the unit square, then building a deformed geometry
108
+ # from an implicit mapping field
109
+ square_geo = fem.Grid2D(
110
+ bounds_lo=wp.vec2(-domain_radius, -domain_radius),
111
+ bounds_hi=wp.vec2(domain_radius, domain_radius),
112
+ res=wp.vec2i(resolution, resolution),
113
+ )
114
+
115
+ def_field = fem.ImplicitField(domain=fem.Cells(square_geo), func=square_to_disk, grad_func=square_to_disk_grad)
116
+ disk_geo = def_field.make_deformed_geometry(relative=False)
117
+
118
+ coil_config = {"coil_height": 1.0, "coil_internal_radius": 0.1, "coil_external_radius": 0.3}
119
+
120
+ domain = fem.Cells(disk_geo)
121
+ self._permeability_field = fem.ImplicitField(domain, func=permeability_field, values=coil_config)
122
+ self._current_field = fem.ImplicitField(domain, func=current_field, values=dict(current=current, **coil_config))
123
+
124
+ z_space = fem.make_polynomial_space(disk_geo, degree=degree, element_basis=fem.ElementBasis.LAGRANGE)
125
+ xy_space = fem.make_polynomial_space(
126
+ disk_geo, degree=degree, element_basis=fem.ElementBasis.LAGRANGE, dtype=wp.vec2
127
+ )
128
+
129
+ self.A_field = z_space.make_field()
130
+ self.B_field = xy_space.make_field()
131
+
132
+ self.renderer = fem_example_utils.Plot()
133
+
134
+ def step(self):
135
+ z_space = self.A_field.space
136
+ disk_geo = z_space.geometry
137
+
138
+ u = fem.make_trial(space=z_space)
139
+ v = fem.make_test(space=z_space)
140
+ lhs = fem.integrate(curl_curl_form, fields={"u": u, "v": v, "mu": self._permeability_field})
141
+ rhs = fem.integrate(mass_form, fields={"v": v, "u": self._current_field})
142
+
143
+ # Dirichlet BC
144
+ boundary = fem.BoundarySides(disk_geo)
145
+ u_bd = fem.make_trial(space=z_space, domain=boundary)
146
+ v_bd = fem.make_test(space=z_space, domain=boundary)
147
+ dirichlet_bd_proj = fem.integrate(mass_form, fields={"u": u_bd, "v": v_bd}, nodal=True)
148
+ fem.project_linear_system(lhs, rhs, dirichlet_bd_proj)
149
+
150
+ x = wp.zeros_like(rhs)
151
+ fem_example_utils.bsr_cg(lhs, b=rhs, x=x, tol=1.0e-8, quiet=False)
152
+
153
+ # make sure result is exactly zero outisde of circle
154
+ wp.sparse.bsr_mv(dirichlet_bd_proj, x=x, y=x, alpha=-1.0, beta=1.0)
155
+ wp.utils.array_cast(in_array=x, out_array=self.A_field.dof_values)
156
+
157
+ # compute B as curl(A)
158
+ fem.interpolate(curl_z, dest=self.B_field, fields={"u": self.A_field})
159
+
160
+ def render(self):
161
+ self.renderer.add_field("A", self.A_field)
162
+ self.renderer.add_field("B", self.B_field)
163
+
164
+
165
+ if __name__ == "__main__":
166
+ import argparse
167
+
168
+ wp.set_module_options({"enable_backward": False})
169
+
170
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
171
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
172
+ parser.add_argument("--resolution", type=int, default=32, help="Grid resolution.")
173
+ parser.add_argument("--degree", type=int, default=2, help="Polynomial degree of shape functions.")
174
+ parser.add_argument("--radius", type=float, default=2.0, help="Radius of simulation domain.")
175
+ parser.add_argument(
176
+ "--headless",
177
+ action="store_true",
178
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
179
+ )
180
+ parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
181
+
182
+ args = parser.parse_known_args()[0]
183
+
184
+ with wp.ScopedDevice(args.device):
185
+ example = Example(quiet=args.quiet, degree=args.degree, resolution=args.resolution, domain_radius=args.radius)
186
+ example.step()
187
+ example.render()
188
+
189
+ if not args.headless:
190
+ example.renderer.plot({"A": {"contours": {"levels": 30}}, "B": {"streamlines": {"density": 1.0}}})