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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) 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.so +0 -0
  57. warp/bin/warp.so +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/fem/field/discrete_field.py +0 -80
  257. warp/fem/space/nodal_function_space.py +0 -233
  258. warp/tests/test_all.py +0 -223
  259. warp/tests/test_array_scan.py +0 -60
  260. warp/tests/test_base.py +0 -208
  261. warp/tests/test_unresolved_func.py +0 -7
  262. warp/tests/test_unresolved_symbol.py +0 -7
  263. warp_lang-1.0.0b2.dist-info/METADATA +0 -26
  264. warp_lang-1.0.0b2.dist-info/RECORD +0 -378
  265. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  266. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  267. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  268. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  269. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
warp/fem/field/test.py CHANGED
@@ -4,110 +4,178 @@ from warp.fem.space import SpaceRestriction, FunctionSpace
4
4
  from warp.fem.types import Sample, get_node_index_in_element
5
5
  from warp.fem import utils, cache
6
6
 
7
+ from .field import SpaceField
7
8
 
8
- class TestField:
9
- """Field defined over a space restriction that can be used as a test function"""
10
9
 
11
- def __init__(self, space_restriction: SpaceRestriction):
10
+ class TestField(SpaceField):
11
+ """Field defined over a space restriction that can be used as a test function.
12
+
13
+ In order to reuse computations, it is possible to define the test field using a SpaceRestriction
14
+ defined for a different value type than the test function value type, as long as the node topology is similar.
15
+ """
16
+
17
+ def __init__(self, space_restriction: SpaceRestriction, space: FunctionSpace):
18
+ if space_restriction.domain.dimension == space.dimension - 1:
19
+ space = space.trace()
20
+
21
+ if space_restriction.domain.dimension != space.dimension:
22
+ raise ValueError("Incompatible space and domain dimensions")
23
+
24
+ if space.topology != space_restriction.space_topology:
25
+ raise ValueError("Incompatible space and space partition topologies")
26
+
27
+ super().__init__(space, space_restriction.space_partition)
28
+
12
29
  self.space_restriction = space_restriction
13
- self.space_partition = self.space_restriction.space_partition
14
- self.space = self.space_restriction.space
15
30
  self.domain = self.space_restriction.domain
16
- self.name = self.space.name + "Test"
17
31
 
18
- self.eval_degree = TestField._make_eval_degree(self.space)
19
- self.eval_inner = TestField._make_eval_inner(self.space)
20
- self.eval_grad_inner = TestField._make_eval_grad_inner(self.space)
21
- self.eval_outer = TestField._make_eval_outer(self.space)
22
- self.eval_grad_outer = TestField._make_eval_grad_outer(self.space)
23
- self.at_node = TestField._make_at_node(self.space)
32
+ self.EvalArg = self.space.SpaceArg
33
+ self.ElementEvalArg = self._make_element_eval_arg()
34
+
35
+ self.eval_degree = self._make_eval_degree()
36
+ self.eval_inner = self._make_eval_inner()
37
+ self.eval_grad_inner = self._make_eval_grad_inner()
38
+ self.eval_div_inner = self._make_eval_div_inner()
39
+ self.eval_outer = self._make_eval_outer()
40
+ self.eval_grad_outer = self._make_eval_grad_outer()
41
+ self.eval_div_outer = self._make_eval_div_outer()
42
+ self.at_node = self._make_at_node()
24
43
 
25
44
  @property
26
- def EvalArg(self) -> wp.codegen.Struct:
27
- return self.space.SpaceArg
45
+ def name(self) -> str:
46
+ return self.space.name + "Test"
28
47
 
29
48
  def eval_arg_value(self, device) -> wp.codegen.StructInstance:
30
49
  return self.space.space_arg_value(device)
31
50
 
32
- @staticmethod
33
- def _make_eval_degree(space: FunctionSpace):
34
- ORDER = space.ORDER
51
+ def _make_element_eval_arg(self):
52
+ from warp.fem import cache
35
53
 
36
- def degree(args: space.SpaceArg):
37
- return ORDER
54
+ @cache.dynamic_struct(suffix=self.name)
55
+ class ElementEvalArg:
56
+ elt_arg: self.domain.ElementArg
57
+ eval_arg: self.EvalArg
38
58
 
39
- return cache.get_func(degree, space)
59
+ return ElementEvalArg
40
60
 
41
- @staticmethod
42
- def _make_eval_inner(space: FunctionSpace):
43
- def eval_test(args: space.SpaceArg, s: Sample):
44
- weight = space.element_inner_weight(
45
- args,
61
+ def _make_eval_inner(self):
62
+ @cache.dynamic_func(suffix=self.name)
63
+ def eval_test_inner(args: self.ElementEvalArg, s: Sample):
64
+ weight = self.space.element_inner_weight(
65
+ args.elt_arg,
66
+ args.eval_arg,
46
67
  s.element_index,
47
68
  s.element_coords,
48
69
  get_node_index_in_element(s.test_dof),
49
70
  )
50
- return weight * space.unit_dof_value(args, s.test_dof)
71
+ return weight * self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof)
51
72
 
52
- return cache.get_func(eval_test, space.name)
73
+ return eval_test_inner
53
74
 
54
- @staticmethod
55
- def _make_eval_grad_inner(space: FunctionSpace):
56
- if wp.types.type_is_matrix(space.dtype):
57
- # There is no Warp high-order tensor type to represent matrix gradients
75
+ def _make_eval_grad_inner(self):
76
+ if not self.gradient_valid():
58
77
  return None
59
78
 
60
- def eval_nabla_test_inner(args: space.SpaceArg, s: Sample):
61
- nabla_weight = space.element_inner_weight_gradient(
62
- args,
79
+ @cache.dynamic_func(suffix=self.name)
80
+ def eval_nabla_test_inner(args: self.ElementEvalArg, s: Sample):
81
+ nabla_weight = self.space.element_inner_weight_gradient(
82
+ args.elt_arg,
83
+ args.eval_arg,
63
84
  s.element_index,
64
85
  s.element_coords,
65
86
  get_node_index_in_element(s.test_dof),
66
87
  )
88
+ grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
67
89
  return utils.generalized_outer(
68
- nabla_weight,
69
- space.unit_dof_value(args, s.test_dof),
90
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof),
91
+ utils.apply_right(nabla_weight, grad_transform),
92
+ )
93
+
94
+ return eval_nabla_test_inner
95
+
96
+ def _make_eval_div_inner(self):
97
+ if not self.divergence_valid():
98
+ return None
99
+
100
+ @cache.dynamic_func(suffix=self.name)
101
+ def eval_div_test_inner(args: self.ElementEvalArg, s: Sample):
102
+ nabla_weight = self.space.element_inner_weight_gradient(
103
+ args.elt_arg,
104
+ args.eval_arg,
105
+ s.element_index,
106
+ s.element_coords,
107
+ get_node_index_in_element(s.test_dof),
108
+ )
109
+ grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
110
+ return utils.generalized_inner(
111
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof),
112
+ utils.apply_right(nabla_weight, grad_transform),
70
113
  )
71
114
 
72
- return cache.get_func(eval_nabla_test_inner, space.name)
115
+ return eval_div_test_inner
73
116
 
74
- @staticmethod
75
- def _make_eval_outer(space: FunctionSpace):
76
- def eval_test_outer(args: space.SpaceArg, s: Sample):
77
- weight = space.element_outer_weight(
78
- args,
117
+ def _make_eval_outer(self):
118
+ @cache.dynamic_func(suffix=self.name)
119
+ def eval_test_outer(args: self.ElementEvalArg, s: Sample):
120
+ weight = self.space.element_outer_weight(
121
+ args.elt_arg,
122
+ args.eval_arg,
79
123
  s.element_index,
80
124
  s.element_coords,
81
125
  get_node_index_in_element(s.test_dof),
82
126
  )
83
- return weight * space.unit_dof_value(args, s.test_dof)
127
+ return weight * self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof)
84
128
 
85
- return cache.get_func(eval_test_outer, space.name)
129
+ return eval_test_outer
86
130
 
87
- @staticmethod
88
- def _make_eval_grad_outer(space: FunctionSpace):
89
- if wp.types.type_is_matrix(space.dtype):
90
- # There is no Warp high-order tensor type to represent matrix gradients
131
+ def _make_eval_grad_outer(self):
132
+ if not self.gradient_valid():
91
133
  return None
92
134
 
93
- def eval_nabla_test(args: space.SpaceArg, s: Sample):
94
- nabla_weight = space.element_outer_weight_gradient(
95
- args,
135
+ @cache.dynamic_func(suffix=self.name)
136
+ def eval_nabla_test_outer(args: self.ElementEvalArg, s: Sample):
137
+ nabla_weight = self.space.element_outer_weight_gradient(
138
+ args.elt_arg,
139
+ args.eval_arg,
96
140
  s.element_index,
97
141
  s.element_coords,
98
142
  get_node_index_in_element(s.test_dof),
99
143
  )
144
+ grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
100
145
  return utils.generalized_outer(
101
- nabla_weight,
102
- space.unit_dof_value(args, s.test_dof),
146
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof),
147
+ utils.apply_right(nabla_weight, grad_transform),
103
148
  )
104
149
 
105
- return cache.get_func(eval_nabla_test, space.name)
150
+ return eval_nabla_test_outer
106
151
 
107
- @staticmethod
108
- def _make_at_node(space: FunctionSpace):
109
- def at_node(args: space.SpaceArg, s: Sample):
110
- node_coords = space.node_coords_in_element(args, s.element_index, get_node_index_in_element(s.test_dof))
152
+ def _make_eval_div_outer(self):
153
+ if not self.divergence_valid():
154
+ return None
155
+
156
+ @cache.dynamic_func(suffix=self.name)
157
+ def eval_div_test_outer(args: self.ElementEvalArg, s: Sample):
158
+ nabla_weight = self.space.element_outer_weight_gradient(
159
+ args.elt_arg,
160
+ args.eval_arg,
161
+ s.element_index,
162
+ s.element_coords,
163
+ get_node_index_in_element(s.test_dof),
164
+ )
165
+ grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
166
+ return utils.generalized_inner(
167
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.test_dof),
168
+ utils.apply_right(nabla_weight, grad_transform),
169
+ )
170
+
171
+ return eval_div_test_outer
172
+
173
+ def _make_at_node(self):
174
+ @cache.dynamic_func(suffix=self.name)
175
+ def at_node(args: self.ElementEvalArg, s: Sample):
176
+ node_coords = self.space.node_coords_in_element(
177
+ args.elt_arg, args.eval_arg, s.element_index, get_node_index_in_element(s.test_dof)
178
+ )
111
179
  return Sample(s.element_index, node_coords, s.qp_index, s.qp_weight, s.test_dof, s.trial_dof)
112
180
 
113
- return cache.get_func(at_node, space.name)
181
+ return at_node
warp/fem/field/trial.py CHANGED
@@ -4,8 +4,10 @@ from warp.fem.space import FunctionSpace, SpacePartition
4
4
  from warp.fem.types import Sample, get_node_index_in_element
5
5
  from warp.fem import utils, cache
6
6
 
7
+ from .field import SpaceField
7
8
 
8
- class TrialField:
9
+
10
+ class TrialField(SpaceField):
9
11
  """Field defined over a domain that can be used as a trial function"""
10
12
 
11
13
  def __init__(
@@ -14,113 +16,168 @@ class TrialField:
14
16
  space_partition: SpacePartition,
15
17
  domain: GeometryDomain,
16
18
  ):
17
- if domain.dimension() == space.DIMENSION - 1:
19
+ if domain.dimension == space.dimension - 1:
18
20
  space = space.trace()
19
21
 
20
- if domain.dimension() != space.DIMENSION:
22
+ if domain.dimension != space.dimension:
21
23
  raise ValueError("Incompatible space and domain dimensions")
22
24
 
23
- self.space = space
25
+ if not space.topology.is_derived_from(space_partition.space_topology):
26
+ raise ValueError("Incompatible space and space partition topologies")
27
+
28
+ super().__init__(space, space_partition)
29
+
24
30
  self.domain = domain
25
- self.space_partition = space_partition
26
- self.name = self.space.name + "Trial"
27
31
 
28
- self.eval_degree = TrialField._make_eval_degree(self.space)
29
- self.eval_inner = TrialField._make_eval_inner(self.space)
30
- self.eval_grad_inner = TrialField._make_eval_grad_inner(self.space)
31
- self.eval_outer = TrialField._make_eval_outer(self.space)
32
- self.eval_grad_outer = TrialField._make_eval_grad_outer(self.space)
33
- self.at_node = TrialField._make_at_node(self.space)
32
+ self.EvalArg = self.space.SpaceArg
33
+ self.ElementEvalArg = self._make_element_eval_arg()
34
+
35
+ self.eval_degree = self._make_eval_degree()
36
+ self.eval_inner = self._make_eval_inner()
37
+ self.eval_grad_inner = self._make_eval_grad_inner()
38
+ self.eval_div_inner = self._make_eval_div_inner()
39
+ self.eval_outer = self._make_eval_outer()
40
+ self.eval_grad_outer = self._make_eval_grad_outer()
41
+ self.eval_div_outer = self._make_eval_div_outer()
42
+ self.at_node = self._make_at_node()
34
43
 
35
44
  def partition_node_count(self) -> int:
45
+ """Returns the number of nodes in the associated space topology partition"""
36
46
  return self.space_partition.node_count()
37
47
 
38
48
  @property
39
- def EvalArg(self) -> wp.codegen.Struct:
40
- return self.space.SpaceArg
49
+ def name(self) -> str:
50
+ return self.space.name + "Trial"
41
51
 
42
52
  def eval_arg_value(self, device) -> wp.codegen.StructInstance:
43
53
  return self.space.space_arg_value(device)
44
54
 
45
- @staticmethod
46
- def _make_eval_degree(space: FunctionSpace):
47
- ORDER = space.ORDER
48
-
49
- def degree(args: space.SpaceArg):
50
- return ORDER
55
+ def _make_element_eval_arg(self):
56
+ @cache.dynamic_struct(suffix=self.name)
57
+ class ElementEvalArg:
58
+ elt_arg: self.domain.ElementArg
59
+ eval_arg: self.EvalArg
51
60
 
52
- return cache.get_func(degree, space)
61
+ return ElementEvalArg
53
62
 
54
- @staticmethod
55
- def _make_eval_inner(space: FunctionSpace):
56
- def eval_trial(args: space.SpaceArg, s: Sample):
57
- weight = space.element_inner_weight(
58
- args,
63
+ def _make_eval_inner(self):
64
+ @cache.dynamic_func(suffix=self.name)
65
+ def eval_trial_inner(args: self.ElementEvalArg, s: Sample):
66
+ weight = self.space.element_inner_weight(
67
+ args.elt_arg,
68
+ args.eval_arg,
59
69
  s.element_index,
60
70
  s.element_coords,
61
71
  get_node_index_in_element(s.trial_dof),
62
72
  )
63
- return weight * space.unit_dof_value(args, s.trial_dof)
73
+ return weight * self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof)
64
74
 
65
- return cache.get_func(eval_trial, space.name)
75
+ return eval_trial_inner
66
76
 
67
- @staticmethod
68
- def _make_eval_grad_inner(space: FunctionSpace):
69
- if wp.types.type_is_matrix(space.dtype):
70
- # There is no Warp high-order tensor type to represent matrix gradients
77
+ def _make_eval_grad_inner(self):
78
+ if not self.gradient_valid():
71
79
  return None
72
80
 
73
- def eval_nabla_trial(args: space.SpaceArg, s: Sample):
74
- nabla_weight = space.element_inner_weight_gradient(
75
- args,
81
+ @cache.dynamic_func(suffix=self.name)
82
+ def eval_nabla_trial_inner(args: self.ElementEvalArg, s: Sample):
83
+ nabla_weight = self.space.element_inner_weight_gradient(
84
+ args.elt_arg,
85
+ args.eval_arg,
76
86
  s.element_index,
77
87
  s.element_coords,
78
88
  get_node_index_in_element(s.trial_dof),
79
89
  )
90
+ grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
80
91
  return utils.generalized_outer(
81
- nabla_weight,
82
- space.unit_dof_value(args, s.trial_dof),
92
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof),
93
+ utils.apply_right(nabla_weight, grad_transform),
94
+ )
95
+
96
+ return eval_nabla_trial_inner
97
+
98
+ def _make_eval_div_inner(self):
99
+ if not self.divergence_valid():
100
+ return None
101
+
102
+ @cache.dynamic_func(suffix=self.name)
103
+ def eval_div_trial_inner(args: self.ElementEvalArg, s: Sample):
104
+ nabla_weight = self.space.element_inner_weight_gradient(
105
+ args.elt_arg,
106
+ args.eval_arg,
107
+ s.element_index,
108
+ s.element_coords,
109
+ get_node_index_in_element(s.trial_dof),
110
+ )
111
+ grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
112
+ return utils.generalized_inner(
113
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof),
114
+ utils.apply_right(nabla_weight, grad_transform),
83
115
  )
84
116
 
85
- return cache.get_func(eval_nabla_trial, space.name)
117
+ return eval_div_trial_inner
86
118
 
87
- @staticmethod
88
- def _make_eval_outer(space: FunctionSpace):
89
- def eval_trial_outer(args: space.SpaceArg, s: Sample):
90
- weight = space.element_outer_weight(
91
- args,
119
+ def _make_eval_outer(self):
120
+ @cache.dynamic_func(suffix=self.name)
121
+ def eval_trial_outer(args: self.ElementEvalArg, s: Sample):
122
+ weight = self.space.element_outer_weight(
123
+ args.elt_arg,
124
+ args.eval_arg,
92
125
  s.element_index,
93
126
  s.element_coords,
94
127
  get_node_index_in_element(s.trial_dof),
95
128
  )
96
- return weight * space.unit_dof_value(args, s.trial_dof)
129
+ return weight * self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof)
97
130
 
98
- return cache.get_func(eval_trial_outer, space.name)
131
+ return eval_trial_outer
99
132
 
100
- @staticmethod
101
- def _make_eval_grad_outer(space: FunctionSpace):
102
- if wp.types.type_is_matrix(space.dtype):
103
- # There is no Warp high-order tensor type to represent matrix gradients
133
+ def _make_eval_grad_outer(self):
134
+ if not self.gradient_valid():
104
135
  return None
105
136
 
106
- def eval_nabla_trial_outer(args: space.SpaceArg, s: Sample):
107
- nabla_weight = space.element_outer_weight_gradient(
108
- args,
137
+ @cache.dynamic_func(suffix=self.name)
138
+ def eval_nabla_trial_outer(args: self.ElementEvalArg, s: Sample):
139
+ nabla_weight = self.space.element_outer_weight_gradient(
140
+ args.elt_arg,
141
+ args.eval_arg,
109
142
  s.element_index,
110
143
  s.element_coords,
111
144
  get_node_index_in_element(s.trial_dof),
112
145
  )
146
+ grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
113
147
  return utils.generalized_outer(
114
- nabla_weight,
115
- space.unit_dof_value(args, s.trial_dof),
148
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof),
149
+ utils.apply_right(nabla_weight, grad_transform),
150
+ )
151
+
152
+ return eval_nabla_trial_outer
153
+
154
+ def _make_eval_div_outer(self):
155
+ if not self.divergence_valid():
156
+ return None
157
+
158
+ @cache.dynamic_func(suffix=self.name)
159
+ def eval_div_trial_outer(args: self.ElementEvalArg, s: Sample):
160
+ nabla_weight = self.space.element_outer_weight_gradient(
161
+ args.elt_arg,
162
+ args.eval_arg,
163
+ s.element_index,
164
+ s.element_coords,
165
+ get_node_index_in_element(s.trial_dof),
166
+ )
167
+ grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
168
+ return utils.generalized_inner(
169
+ self.space.unit_dof_value(args.elt_arg, args.eval_arg, s.trial_dof),
170
+ utils.apply_right(nabla_weight, grad_transform),
116
171
  )
117
172
 
118
- return cache.get_func(eval_nabla_trial_outer, space.name)
173
+ return eval_div_trial_outer
119
174
 
120
- @staticmethod
121
- def _make_at_node(space: FunctionSpace):
122
- def at_node(args: space.SpaceArg, s: Sample):
123
- node_coords = space.node_coords_in_element(args, s.element_index, get_node_index_in_element(s.trial_dof))
175
+ def _make_at_node(self):
176
+ @cache.dynamic_func(suffix=self.name)
177
+ def at_node(args: self.ElementEvalArg, s: Sample):
178
+ node_coords = self.space.node_coords_in_element(
179
+ args.elt_arg, args.eval_arg, s.element_index, get_node_index_in_element(s.trial_dof)
180
+ )
124
181
  return Sample(s.element_index, node_coords, s.qp_index, s.qp_weight, s.test_dof, s.trial_dof)
125
182
 
126
- return cache.get_func(at_node, space.name)
183
+ return at_node
@@ -1,5 +1,7 @@
1
1
  from .element import Element
2
2
  from .geometry import Geometry
3
+ from .deformed_geometry import DeformedGeometry
4
+
3
5
  from .partition import (
4
6
  GeometryPartition,
5
7
  WholeGeometryPartition,
@@ -12,4 +14,6 @@ from .grid_2d import Grid2D
12
14
  from .grid_3d import Grid3D
13
15
 
14
16
  from .trimesh_2d import Trimesh2D
15
- from .tetmesh import Tetmesh
17
+ from .tetmesh import Tetmesh
18
+ from .quadmesh_2d import Quadmesh2D
19
+ from .hexmesh import Hexmesh