warp-lang 1.2.2__py3-none-win_amd64.whl → 1.3.0__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 (194) hide show
  1. warp/__init__.py +8 -6
  2. warp/autograd.py +823 -0
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +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 +400 -198
  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 +65 -1
  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 +341 -224
  185. warp/utils.py +11 -2
  186. {warp_lang-1.2.2.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.2.dist-info/RECORD +0 -359
  192. {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/LICENSE.md +0 -0
  193. {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/WHEEL +0 -0
  194. {warp_lang-1.2.2.dist-info → warp_lang-1.3.0.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
1
1
  import warp as wp
2
2
  from warp.fem.cache import TemporaryStore, borrow_temporary, borrow_temporary_like, cached_arg_value
3
3
  from warp.fem.domain import GeometryDomain
4
- from warp.fem.types import NodeElementIndex
4
+ from warp.fem.types import NULL_NODE_INDEX, NodeElementIndex
5
5
  from warp.fem.utils import compress_node_indices
6
6
 
7
7
  from .partition import SpacePartition
@@ -36,7 +36,7 @@ class SpaceRestriction:
36
36
  def _compute_node_element_indices(self, device, temporary_store: TemporaryStore):
37
37
  from warp.fem import cache
38
38
 
39
- NODES_PER_ELEMENT = self.space_topology.NODES_PER_ELEMENT
39
+ MAX_NODES_PER_ELEMENT = self.space_topology.MAX_NODES_PER_ELEMENT
40
40
 
41
41
  @cache.dynamic_kernel(
42
42
  suffix=f"{self.domain.name}_{self.space_topology.name}_{self.space_partition.name}",
@@ -51,14 +51,17 @@ class SpaceRestriction:
51
51
  ):
52
52
  domain_element_index = wp.tid()
53
53
  element_index = self.domain.element_index(domain_index_arg, domain_element_index)
54
- for n in range(NODES_PER_ELEMENT):
54
+ element_node_count = self.space_topology.element_node_count(element_arg, topo_arg, element_index)
55
+ for n in range(element_node_count):
55
56
  space_nidx = self.space_topology.element_node_index(element_arg, topo_arg, element_index, n)
56
57
  partition_nidx = self.space_partition.partition_node_index(partition_arg, space_nidx)
57
58
  element_node_indices[domain_element_index, n] = partition_nidx
59
+ for n in range(element_node_count, MAX_NODES_PER_ELEMENT):
60
+ element_node_indices[domain_element_index, n] = NULL_NODE_INDEX
58
61
 
59
62
  element_node_indices = borrow_temporary(
60
63
  temporary_store,
61
- shape=(self.domain.element_count(), NODES_PER_ELEMENT),
64
+ shape=(self.domain.element_count(), MAX_NODES_PER_ELEMENT),
62
65
  dtype=int,
63
66
  device=device,
64
67
  )
@@ -83,7 +86,10 @@ class SpaceRestriction:
83
86
  self._node_count,
84
87
  self._dof_partition_indices,
85
88
  ) = compress_node_indices(
86
- self.space_partition.node_count(), flattened_node_indices, temporary_store=temporary_store
89
+ self.space_partition.node_count(),
90
+ flattened_node_indices,
91
+ return_unique_nodes=True,
92
+ temporary_store=temporary_store,
87
93
  )
88
94
 
89
95
  # Extract element index and index in element
@@ -93,7 +99,7 @@ class SpaceRestriction:
93
99
  kernel=SpaceRestriction._split_vertex_element_index,
94
100
  dim=flattened_node_indices.shape,
95
101
  inputs=[
96
- NODES_PER_ELEMENT,
102
+ MAX_NODES_PER_ELEMENT,
97
103
  node_array_indices.array,
98
104
  self._dof_element_indices.array,
99
105
  self._dof_indices_in_element.array,
@@ -132,20 +138,17 @@ class SpaceRestriction:
132
138
  return arg
133
139
 
134
140
  @wp.func
135
- def node_partition_index(args: NodeArg, node_index: int):
136
- return args.dof_partition_indices[node_index]
141
+ def node_partition_index(args: NodeArg, restriction_node_index: int):
142
+ return args.dof_partition_indices[restriction_node_index]
137
143
 
138
144
  @wp.func
139
- def node_element_count(args: NodeArg, node_index: int):
140
- partition_node_index = SpaceRestriction.node_partition_index(args, node_index)
141
- return args.dof_element_offsets[partition_node_index + 1] - args.dof_element_offsets[partition_node_index]
145
+ def node_element_range(args: NodeArg, partition_node_index: int):
146
+ return args.dof_element_offsets[partition_node_index], args.dof_element_offsets[partition_node_index + 1]
142
147
 
143
148
  @wp.func
144
- def node_element_index(args: NodeArg, node_index: int, element_index: int):
145
- partition_node_index = SpaceRestriction.node_partition_index(args, node_index)
146
- offset = args.dof_element_offsets[partition_node_index] + element_index
147
- domain_element_index = args.dof_element_indices[offset]
148
- index_in_element = args.dof_indices_in_element[offset]
149
+ def node_element_index(args: NodeArg, node_element_offset: int):
150
+ domain_element_index = args.dof_element_indices[node_element_offset]
151
+ index_in_element = args.dof_indices_in_element[node_element_offset]
149
152
  return NodeElementIndex(domain_element_index, index_in_element)
150
153
 
151
154
  @wp.kernel
@@ -98,7 +98,7 @@ class CubeTripolynomialShapeFunctions:
98
98
 
99
99
  # x face
100
100
  type_instance = mi
101
- type_index = wp.select(mi == 1, (j - 1) * (ORDER - 1) + k - 1, (k - 1) * (ORDER - 1) + j - 1)
101
+ type_index = (j - 1) * (ORDER - 1) + k - 1
102
102
  return CubeTripolynomialShapeFunctions.FACE, type_instance, type_index
103
103
 
104
104
  if zj + mj == 1:
@@ -110,13 +110,13 @@ class CubeTripolynomialShapeFunctions:
110
110
 
111
111
  # y face
112
112
  type_instance = 2 + mj
113
- type_index = wp.select(mj == 1, (i - 1) * (ORDER - 1) + k - 1, (k - 1) * (ORDER - 1) + i - 1)
113
+ type_index = (k - 1) * (ORDER - 1) + i - 1
114
114
  return CubeTripolynomialShapeFunctions.FACE, type_instance, type_index
115
115
 
116
116
  if zk + mk == 1:
117
117
  # z face
118
118
  type_instance = 4 + mk
119
- type_index = wp.select(mk == 1, (j - 1) * (ORDER - 1) + i - 1, (i - 1) * (ORDER - 1) + j - 1)
119
+ type_index = (i - 1) * (ORDER - 1) + j - 1
120
120
  return CubeTripolynomialShapeFunctions.FACE, type_instance, type_index
121
121
 
122
122
  type_index = ((i - 1) * (ORDER - 1) + (j - 1)) * (ORDER - 1) + k - 1
@@ -322,6 +322,87 @@ class CubeTripolynomialShapeFunctions:
322
322
 
323
323
  return grid_to_tets(self.ORDER, self.ORDER, self.ORDER)
324
324
 
325
+ def element_vtk_cells(self):
326
+ n = self.ORDER + 1
327
+
328
+ # vertices
329
+ cells = [
330
+ [
331
+ [0, 0, 0],
332
+ [n - 1, 0, 0],
333
+ [n - 1, n - 1, 0],
334
+ [0, n - 1, 0],
335
+ [0, 0, n - 1],
336
+ [n - 1, 0, n - 1],
337
+ [n - 1, n - 1, n - 1],
338
+ [0, n - 1, n - 1],
339
+ ]
340
+ ]
341
+
342
+ if self.ORDER == 1:
343
+ cell_type = 12 # vtk_hexahedron
344
+ else:
345
+ middle = np.arange(1, n - 1)
346
+ front = np.zeros(n - 2, dtype=int)
347
+ back = np.full(n - 2, n - 1)
348
+
349
+ # edges
350
+ cells.append(np.column_stack((middle, front, front)))
351
+ cells.append(np.column_stack((back, middle, front)))
352
+ cells.append(np.column_stack((middle, back, front)))
353
+ cells.append(np.column_stack((front, middle, front)))
354
+
355
+ cells.append(np.column_stack((middle, front, back)))
356
+ cells.append(np.column_stack((back, middle, back)))
357
+ cells.append(np.column_stack((middle, back, back)))
358
+ cells.append(np.column_stack((front, middle, back)))
359
+
360
+ cells.append(np.column_stack((front, front, middle)))
361
+ cells.append(np.column_stack((back, front, middle)))
362
+ cells.append(np.column_stack((back, back, middle)))
363
+ cells.append(np.column_stack((front, back, middle)))
364
+
365
+ # faces
366
+
367
+ face = np.meshgrid(middle, middle)
368
+ front = np.zeros((n - 2) ** 2, dtype=int)
369
+ back = np.full((n - 2) ** 2, n - 1)
370
+
371
+ # YZ
372
+ cells.append(
373
+ np.column_stack((front, face[0].flatten(), face[1].flatten())),
374
+ )
375
+ cells.append(
376
+ np.column_stack((back, face[0].flatten(), face[1].flatten())),
377
+ )
378
+ # XZ
379
+ cells.append(
380
+ np.column_stack((face[0].flatten(), front, face[1].flatten())),
381
+ )
382
+ cells.append(
383
+ np.column_stack((face[0].flatten(), back, face[1].flatten())),
384
+ )
385
+ # XY
386
+ cells.append(
387
+ np.column_stack((face[0].flatten(), face[1].flatten(), front)),
388
+ )
389
+ cells.append(
390
+ np.column_stack((face[0].flatten(), face[1].flatten(), back)),
391
+ )
392
+
393
+ # interior
394
+ interior = np.meshgrid(middle, middle, middle)
395
+ cells.append(
396
+ np.column_stack((interior[0].flatten(), interior[1].flatten(), interior[2].flatten())),
397
+ )
398
+
399
+ cell_type = 72 # vtk_lagrange_hexahedron
400
+
401
+ cells = np.concatenate(cells)
402
+ cell_indices = cells[:, 0] * n * n + cells[:, 1] * n + cells[:, 2]
403
+
404
+ return cell_indices[np.newaxis, :], np.array([cell_type], dtype=np.int8)
405
+
325
406
 
326
407
  class CubeSerendipityShapeFunctions:
327
408
  """
@@ -632,6 +713,12 @@ class CubeSerendipityShapeFunctions:
632
713
 
633
714
  raise NotImplementedError()
634
715
 
716
+ def element_vtk_cells(self):
717
+ tets = np.array(self.element_node_tets())
718
+ cell_type = 10 # VTK_TETRA
719
+
720
+ return tets, np.full(tets.shape[0], cell_type, dtype=np.int8)
721
+
635
722
 
636
723
  class CubeNonConformingPolynomialShapeFunctions:
637
724
  # embeds the largest regular tet centered at (0.5, 0.5, 0.5) into the reference cube
@@ -656,6 +743,7 @@ class CubeNonConformingPolynomialShapeFunctions:
656
743
  self.NODES_PER_ELEMENT = self._tet_shape.NODES_PER_ELEMENT
657
744
 
658
745
  self.element_node_tets = self._tet_shape.element_node_tets
746
+ self.element_vtk_cells = self._tet_shape.element_vtk_cells
659
747
 
660
748
  @property
661
749
  def name(self) -> str:
@@ -1,3 +1,5 @@
1
+ import numpy as np
2
+
1
3
  import warp as wp
2
4
  from warp.fem import cache
3
5
  from warp.fem.geometry import Element
@@ -100,3 +102,8 @@ class ConstantShapeFunction:
100
102
  return grad_type(0.0)
101
103
 
102
104
  return element_inner_weight_gradient
105
+
106
+ def element_vtk_cells(self):
107
+ cell_type = 1 # VTK_VERTEX
108
+
109
+ return np.zeros((1, 1), dtype=int), np.full(1, cell_type, dtype=np.int8)
@@ -206,6 +206,31 @@ class SquareBipolynomialShapeFunctions:
206
206
 
207
207
  return grid_to_tris(self.ORDER, self.ORDER)
208
208
 
209
+ def element_vtk_cells(self):
210
+ n = self.ORDER + 1
211
+
212
+ # vertices
213
+ cells = [[0, (n - 1) * n, n * n - 1, n - 1]]
214
+
215
+ if self.ORDER == 1:
216
+ cell_type = 9 # VTK_QUAD
217
+ else:
218
+ middle = np.arange(1, n - 1)
219
+
220
+ # edges
221
+ cells.append(middle * n)
222
+ cells.append(middle + (n - 1) * n)
223
+ cells.append(middle * n + n - 1)
224
+ cells.append(middle)
225
+
226
+ # faces
227
+ interior = np.broadcast_to(middle, (n - 2, n - 2))
228
+ cells.append((interior * n + interior.transpose()).flatten())
229
+
230
+ cell_type = 70 # VTK_LAGRANGE_QUADRILATERAL
231
+
232
+ return np.concatenate(cells)[np.newaxis, :], np.array([cell_type], dtype=np.int8)
233
+
209
234
 
210
235
  class SquareSerendipityShapeFunctions:
211
236
  """
@@ -501,6 +526,12 @@ class SquareSerendipityShapeFunctions:
501
526
 
502
527
  return element_triangles
503
528
 
529
+ def element_vtk_cells(self):
530
+ tris = np.array(self.element_node_triangulation())
531
+ cell_type = 5 # VTK_TRIANGLE
532
+
533
+ return tris, np.full(tris.shape[0], cell_type, dtype=np.int8)
534
+
504
535
 
505
536
  class SquareNonConformingPolynomialShapeFunctions:
506
537
  # embeds the largest equilateral triangle centered at (0.5, 0.5) into the reference square
@@ -516,6 +547,7 @@ class SquareNonConformingPolynomialShapeFunctions:
516
547
  self.NODES_PER_ELEMENT = self._tri_shape.NODES_PER_ELEMENT
517
548
 
518
549
  self.element_node_triangulation = self._tri_shape.element_node_triangulation
550
+ self.element_vtk_cells = self._tri_shape.element_vtk_cells
519
551
 
520
552
  @property
521
553
  def name(self) -> str:
@@ -92,7 +92,6 @@ def _tet_node_index(tx: int, ty: int, tz: int, degree: int):
92
92
 
93
93
 
94
94
  class TetrahedronPolynomialShapeFunctions:
95
- INVALID = wp.constant(-1)
96
95
  VERTEX = wp.constant(0)
97
96
  EDGE = wp.constant(1)
98
97
  FACE = wp.constant(2)
@@ -138,14 +137,10 @@ class TetrahedronPolynomialShapeFunctions:
138
137
 
139
138
  def _get_node_type_and_type_index(self):
140
139
  ORDER = self.ORDER
141
- NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
142
140
 
143
141
  def node_type_and_index(
144
142
  node_index_in_elt: int,
145
143
  ):
146
- if node_index_in_elt < 0 or node_index_in_elt >= NODES_PER_ELEMENT:
147
- return TetrahedronPolynomialShapeFunctions.INVALID, TetrahedronPolynomialShapeFunctions.INVALID
148
-
149
144
  if node_index_in_elt < 4:
150
145
  return TetrahedronPolynomialShapeFunctions.VERTEX, node_index_in_elt
151
146
 
@@ -208,7 +203,7 @@ class TetrahedronPolynomialShapeFunctions:
208
203
 
209
204
  def make_trace_node_quadrature_weight(self):
210
205
  if self.ORDER == 3:
211
- # P3 intrisic quadrature
206
+ # P3 intrinsic quadrature
212
207
  vertex_weight = 1.0 / 30
213
208
  edge_weight = 0.075
214
209
  interior_weight = 0.45
@@ -447,6 +442,14 @@ class TetrahedronPolynomialShapeFunctions:
447
442
 
448
443
  return np.array(element_tets)
449
444
 
445
+ def element_vtk_cells(self):
446
+ cells = np.arange(self.NODES_PER_ELEMENT)
447
+ if self.ORDER == 1:
448
+ cell_type = 10 # VTK_TETRA
449
+ else:
450
+ cell_type = 71 # VTK_LAGRANGE_TETRAHEDRON
451
+ return cells[np.newaxis, :], np.array([cell_type], dtype=np.int8)
452
+
450
453
 
451
454
  class TetrahedronNonConformingPolynomialShapeFunctions:
452
455
  def __init__(self, degree: int):
@@ -455,6 +458,7 @@ class TetrahedronNonConformingPolynomialShapeFunctions:
455
458
  self.NODES_PER_ELEMENT = self._tet_shape.NODES_PER_ELEMENT
456
459
 
457
460
  self.element_node_tets = self._tet_shape.element_node_tets
461
+ self.element_vtk_cells = self._tet_shape.element_vtk_cells
458
462
 
459
463
  if self.ORDER == 1:
460
464
  self._TET_SCALE = 0.4472135955 # so v at 0.5854101966249680 (order 2)
@@ -489,7 +493,7 @@ class TetrahedronNonConformingPolynomialShapeFunctions:
489
493
 
490
494
  def make_node_quadrature_weight(self):
491
495
  # Intrinsic quadrature -- precomputed integral of node shape functions
492
- # over element. Order euqla to self.ORDER
496
+ # over element. Order equal to self.ORDER
493
497
 
494
498
  if self.ORDER == 2:
495
499
  vertex_weight = 0.07499641
@@ -103,7 +103,7 @@ class Triangle2DPolynomialShapeFunctions:
103
103
 
104
104
  def make_node_quadrature_weight(self):
105
105
  if self.ORDER == 3:
106
- # P3 intrisic quadrature
106
+ # P3 intrinsic quadrature
107
107
  vertex_weight = 1.0 / 30
108
108
  edge_weight = 0.075
109
109
  interior_weight = 0.45
@@ -309,6 +309,14 @@ class Triangle2DPolynomialShapeFunctions:
309
309
 
310
310
  return np.array(element_triangles)
311
311
 
312
+ def element_vtk_cells(self):
313
+ cells = np.arange(self.NODES_PER_ELEMENT)
314
+ if self.ORDER == 1:
315
+ cell_type = 5 # VTK_TRIANGLE
316
+ else:
317
+ cell_type = 69 # VTK_LAGRANGE_TRIANGLE
318
+ return cells[np.newaxis, :], np.array([cell_type], dtype=np.int8)
319
+
312
320
 
313
321
  class Triangle2DNonConformingPolynomialShapeFunctions:
314
322
  def __init__(self, degree: int):
@@ -317,6 +325,7 @@ class Triangle2DNonConformingPolynomialShapeFunctions:
317
325
  self.NODES_PER_ELEMENT = self._tri_shape.NODES_PER_ELEMENT
318
326
 
319
327
  self.element_node_triangulation = self._tri_shape.element_node_triangulation
328
+ self.element_vtk_cells = self._tri_shape.element_vtk_cells
320
329
 
321
330
  # Coordinates (a, b, b) of embedded triangle
322
331
  if self.ORDER == 1: