warp-lang 0.10.1__py3-none-win_amd64.whl → 0.11.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.
- warp/__init__.py +10 -4
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +5 -3
- warp/build_dll.py +29 -9
- warp/builtins.py +868 -507
- warp/codegen.py +1074 -638
- warp/config.py +3 -3
- warp/constants.py +6 -0
- warp/context.py +715 -222
- warp/fabric.py +326 -0
- warp/fem/__init__.py +27 -0
- warp/fem/cache.py +389 -0
- warp/fem/dirichlet.py +181 -0
- warp/fem/domain.py +263 -0
- warp/fem/field/__init__.py +101 -0
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +299 -0
- warp/fem/field/restriction.py +21 -0
- warp/fem/field/test.py +181 -0
- warp/fem/field/trial.py +183 -0
- warp/fem/geometry/__init__.py +19 -0
- warp/fem/geometry/closest_point.py +70 -0
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +744 -0
- warp/fem/geometry/geometry.py +186 -0
- warp/fem/geometry/grid_2d.py +373 -0
- warp/fem/geometry/grid_3d.py +435 -0
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +376 -0
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +840 -0
- warp/fem/geometry/trimesh_2d.py +577 -0
- warp/fem/integrate.py +1616 -0
- warp/fem/operator.py +191 -0
- warp/fem/polynomial.py +213 -0
- warp/fem/quadrature/__init__.py +2 -0
- warp/fem/quadrature/pic_quadrature.py +245 -0
- warp/fem/quadrature/quadrature.py +294 -0
- warp/fem/space/__init__.py +292 -0
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +236 -0
- warp/fem/space/function_space.py +145 -0
- warp/fem/space/grid_2d_function_space.py +267 -0
- warp/fem/space/grid_3d_function_space.py +306 -0
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +350 -0
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +160 -0
- warp/fem/space/shape/__init__.py +15 -0
- warp/fem/space/shape/cube_shape_function.py +738 -0
- warp/fem/space/shape/shape_function.py +103 -0
- warp/fem/space/shape/square_shape_function.py +611 -0
- warp/fem/space/shape/tet_shape_function.py +567 -0
- warp/fem/space/shape/triangle_shape_function.py +429 -0
- warp/fem/space/tetmesh_function_space.py +292 -0
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +221 -0
- warp/fem/types.py +77 -0
- warp/fem/utils.py +495 -0
- warp/native/array.h +147 -44
- warp/native/builtin.h +122 -149
- warp/native/bvh.cpp +73 -325
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +34 -43
- warp/native/clang/clang.cpp +13 -8
- warp/native/crt.h +2 -0
- warp/native/cuda_crt.h +5 -0
- warp/native/cuda_util.cpp +15 -3
- warp/native/cuda_util.h +3 -1
- warp/native/cutlass/tools/library/scripts/conv2d_operation.py +463 -0
- warp/native/cutlass/tools/library/scripts/conv3d_operation.py +321 -0
- warp/native/cutlass/tools/library/scripts/gemm_operation.py +988 -0
- warp/native/cutlass/tools/library/scripts/generator.py +4625 -0
- warp/native/cutlass/tools/library/scripts/library.py +799 -0
- warp/native/cutlass/tools/library/scripts/manifest.py +402 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/docs/source/conf.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/conv/conv2d_f16_sm80.py +106 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/profile/gemm/gemm_f32_sm80.py +91 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/setup.py +80 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/__init__.py +48 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/arguments.py +118 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/c_types.py +241 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/compiler.py +432 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/conv2d_operation.py +631 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/epilogue.py +1026 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/frontend.py +104 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/gemm_operation.py +1276 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/library.py +744 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/memory_manager.py +74 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/operation.py +110 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/parser.py +619 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/reduction_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/tensor_ref.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/__init__.py +4 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/conv2d_testbed.py +646 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_grouped_testbed.py +235 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/gemm_testbed.py +557 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/test/profiler.py +70 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/type_hint.py +39 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/__init__.py +1 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/device.py +76 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/src/pycutlass/utils/reference_model.py +255 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +201 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +177 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +98 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_dgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +95 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_few_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +163 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_fixed_channels_f16nhwc_f16nhwc_f16nhwc_tensor_op_f32_sm80.py +187 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +309 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +54 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_fprop_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_strided_dgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +253 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f16nhwc_tensor_op_f16_sm80.py +97 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f16nhwc_f16nhwc_f32nhwc_tensor_op_f32_sm80.py +242 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_f32nhwc_f32nhwc_f32nhwc_simt_f32_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/conv2d_wgrad_implicit_gemm_tf32nhwc_tf32nhwc_f32nhwc_tensor_op_f32_sm80.py +107 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/conv/run_all_tests.py +10 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/frontend/test_frontend.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/__init__.py +0 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_bf16_sm80.py +96 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f16_sm80.py +447 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f32_sm80.py +146 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_f64_sm80.py +102 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_grouped_sm80.py +203 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/gemm_s8_sm80.py +229 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/gemm/run_all_tests.py +9 -0
- warp/native/cutlass/tools/library/scripts/pycutlass/test/unit/test_sm80.py +453 -0
- warp/native/cutlass/tools/library/scripts/rank_2k_operation.py +398 -0
- warp/native/cutlass/tools/library/scripts/rank_k_operation.py +387 -0
- warp/native/cutlass/tools/library/scripts/rt.py +796 -0
- warp/native/cutlass/tools/library/scripts/symm_operation.py +400 -0
- warp/native/cutlass/tools/library/scripts/trmm_operation.py +407 -0
- warp/native/cutlass_gemm.cu +5 -3
- warp/native/exports.h +1240 -952
- warp/native/fabric.h +228 -0
- warp/native/hashgrid.cpp +4 -4
- warp/native/hashgrid.h +22 -2
- warp/native/intersect.h +22 -7
- warp/native/intersect_adj.h +8 -8
- warp/native/intersect_tri.h +1 -1
- warp/native/marching.cu +157 -161
- warp/native/mat.h +80 -19
- warp/native/matnn.h +2 -2
- warp/native/mesh.cpp +33 -108
- warp/native/mesh.cu +114 -23
- warp/native/mesh.h +446 -46
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +45 -35
- warp/native/range.h +6 -2
- warp/native/reduce.cpp +1 -1
- warp/native/reduce.cu +10 -12
- warp/native/runlength_encode.cu +6 -10
- warp/native/scan.cu +8 -11
- warp/native/sparse.cpp +4 -4
- warp/native/sparse.cu +164 -154
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +14 -30
- warp/native/vec.h +107 -23
- warp/native/volume.h +120 -0
- warp/native/warp.cpp +560 -30
- warp/native/warp.cu +431 -44
- warp/native/warp.h +13 -4
- warp/optim/__init__.py +1 -0
- warp/optim/linear.py +922 -0
- warp/optim/sgd.py +92 -0
- warp/render/render_opengl.py +335 -119
- warp/render/render_usd.py +11 -11
- warp/sim/__init__.py +2 -2
- warp/sim/articulation.py +385 -185
- warp/sim/collide.py +8 -0
- warp/sim/import_mjcf.py +297 -106
- warp/sim/import_urdf.py +389 -210
- warp/sim/import_usd.py +198 -97
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_euler.py +14 -8
- warp/sim/integrator_xpbd.py +158 -16
- warp/sim/model.py +795 -291
- warp/sim/render.py +3 -3
- warp/sim/utils.py +3 -0
- warp/sparse.py +640 -150
- warp/stubs.py +606 -267
- warp/tape.py +61 -10
- warp/tests/__main__.py +3 -6
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/disabled_kinematics.py +239 -0
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +103 -106
- warp/tests/test_arithmetic.py +128 -74
- warp/tests/test_array.py +212 -97
- warp/tests/test_array_reduce.py +57 -23
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +99 -0
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +42 -18
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +208 -130
- warp/tests/test_compile_consts.py +28 -20
- warp/tests/test_conditional.py +108 -24
- warp/tests/test_copy.py +10 -12
- warp/tests/test_ctypes.py +112 -88
- warp/tests/test_dense.py +21 -14
- warp/tests/test_devices.py +98 -0
- warp/tests/test_dlpack.py +75 -75
- warp/tests/test_examples.py +277 -0
- warp/tests/test_fabricarray.py +955 -0
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1271 -0
- warp/tests/test_fp16.py +53 -19
- warp/tests/test_func.py +187 -86
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +178 -109
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +52 -37
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +32 -31
- warp/tests/test_intersect.py +18 -9
- warp/tests/test_large.py +141 -0
- warp/tests/test_launch.py +14 -41
- warp/tests/test_lerp.py +64 -65
- warp/tests/test_linear_solvers.py +154 -0
- warp/tests/test_lvalue.py +493 -0
- warp/tests/test_marching_cubes.py +12 -13
- warp/tests/test_mat.py +517 -2898
- warp/tests/test_mat_lite.py +115 -0
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +103 -9
- warp/tests/test_matmul.py +305 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +71 -14
- warp/tests/test_mesh_query_aabb.py +41 -25
- warp/tests/test_mesh_query_point.py +140 -22
- warp/tests/test_mesh_query_ray.py +39 -22
- warp/tests/test_mlp.py +30 -22
- warp/tests/test_model.py +92 -89
- warp/tests/test_modules_lite.py +39 -0
- warp/tests/test_multigpu.py +88 -114
- warp/tests/test_noise.py +12 -11
- warp/tests/test_operators.py +16 -20
- warp/tests/test_options.py +11 -11
- warp/tests/test_pinned.py +17 -18
- warp/tests/test_print.py +32 -11
- warp/tests/test_quat.py +275 -129
- warp/tests/test_rand.py +18 -16
- warp/tests/test_reload.py +38 -34
- warp/tests/test_rounding.py +50 -43
- warp/tests/test_runlength_encode.py +168 -20
- warp/tests/test_smoothstep.py +9 -11
- warp/tests/test_snippet.py +143 -0
- warp/tests/test_sparse.py +261 -63
- warp/tests/test_spatial.py +276 -243
- warp/tests/test_streams.py +110 -85
- warp/tests/test_struct.py +268 -63
- warp/tests/test_tape.py +39 -21
- warp/tests/test_torch.py +118 -89
- warp/tests/test_transient_module.py +12 -13
- warp/tests/test_types.py +614 -0
- warp/tests/test_utils.py +494 -0
- warp/tests/test_vec.py +354 -2050
- warp/tests/test_vec_lite.py +73 -0
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +457 -293
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +341 -0
- warp/tests/unittest_utils.py +568 -0
- warp/tests/unused_test_misc.py +71 -0
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +549 -0
- warp/torch.py +9 -6
- warp/types.py +1089 -366
- warp/utils.py +93 -387
- warp_lang-0.11.0.dist-info/METADATA +238 -0
- warp_lang-0.11.0.dist-info/RECORD +332 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/WHEEL +1 -1
- warp/tests/test_all.py +0 -219
- warp/tests/test_array_scan.py +0 -60
- warp/tests/test_base.py +0 -208
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- warp_lang-0.10.1.dist-info/METADATA +0 -21
- warp_lang-0.10.1.dist-info/RECORD +0 -188
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-0.10.1.dist-info → warp_lang-0.11.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from enum import Enum
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
import warp as wp
|
|
6
|
+
import warp.types
|
|
7
|
+
|
|
8
|
+
vec6 = wp.types.vector(length=6, dtype=wp.float32)
|
|
9
|
+
|
|
10
|
+
_SQRT_2 = wp.constant(math.sqrt(2.0))
|
|
11
|
+
_SQRT_3 = wp.constant(math.sqrt(3.0))
|
|
12
|
+
_SQRT_1_2 = wp.constant(math.sqrt(1.0 / 2.0))
|
|
13
|
+
_SQRT_1_3 = wp.constant(math.sqrt(1.0 / 3.0))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DofMapper:
|
|
17
|
+
"""Base class from mapping node degrees of freedom to function values"""
|
|
18
|
+
|
|
19
|
+
value_dtype: type
|
|
20
|
+
dof_dtype: type
|
|
21
|
+
DOF_SIZE: int
|
|
22
|
+
|
|
23
|
+
@wp.func
|
|
24
|
+
def dof_to_value(dof: Any):
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
@wp.func
|
|
28
|
+
def value_to_dof(val: Any):
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
|
|
31
|
+
def __str__(self):
|
|
32
|
+
return f"{self.value_dtype.__name__}_{self.DOF_SIZE}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class IdentityMapper(DofMapper):
|
|
36
|
+
"""Identity mapper"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, dtype: type):
|
|
39
|
+
if dtype == float:
|
|
40
|
+
dtype = wp.float32
|
|
41
|
+
|
|
42
|
+
self.value_dtype = dtype
|
|
43
|
+
self.dof_dtype = dtype
|
|
44
|
+
|
|
45
|
+
size = warp.types.type_length(dtype)
|
|
46
|
+
self.DOF_SIZE = wp.constant(size)
|
|
47
|
+
|
|
48
|
+
@wp.func
|
|
49
|
+
def dof_to_value(dof: Any):
|
|
50
|
+
return dof
|
|
51
|
+
|
|
52
|
+
@wp.func
|
|
53
|
+
def value_to_dof(val: Any):
|
|
54
|
+
return val
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class SymmetricTensorMapper(DofMapper):
|
|
58
|
+
"""Orthonormal isomorphism from R^{n (n+1)} to nxn symmetric tensors,
|
|
59
|
+
using usual L2 norm for vectors and half Frobenius norm, (tau : tau)/2 for tensors.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
class Mapping(Enum):
|
|
63
|
+
VOIGT = 0
|
|
64
|
+
"""Voigt ordering of vector coefficients:
|
|
65
|
+
first the three diagonal terms, then off-diagonal coefficients"""
|
|
66
|
+
DB16 = 1
|
|
67
|
+
"""Ordering that also separates normal from tangential coefficients:
|
|
68
|
+
first trace, then other diagonal terms, then off-diagonal coefficients.
|
|
69
|
+
See [Daviet and Bertails-Descoubes 2016]"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, dtype: type, mapping: Mapping = Mapping.VOIGT):
|
|
72
|
+
self.value_dtype = dtype
|
|
73
|
+
self.mapping = mapping
|
|
74
|
+
|
|
75
|
+
if dtype == wp.mat22:
|
|
76
|
+
self.dof_dtype = wp.vec3
|
|
77
|
+
self.DOF_SIZE = wp.constant(3)
|
|
78
|
+
if mapping == SymmetricTensorMapper.Mapping.VOIGT:
|
|
79
|
+
self.dof_to_value = SymmetricTensorMapper.dof_to_value_2d_voigt
|
|
80
|
+
self.value_to_dof = SymmetricTensorMapper.value_to_dof_2d_voigt
|
|
81
|
+
else:
|
|
82
|
+
self.dof_to_value = SymmetricTensorMapper.dof_to_value_2d
|
|
83
|
+
self.value_to_dof = SymmetricTensorMapper.value_to_dof_2d
|
|
84
|
+
elif dtype == wp.mat33:
|
|
85
|
+
self.dof_dtype = vec6
|
|
86
|
+
self.DOF_SIZE = wp.constant(6)
|
|
87
|
+
if mapping == SymmetricTensorMapper.Mapping.VOIGT:
|
|
88
|
+
self.dof_to_value = SymmetricTensorMapper.dof_to_value_3d_voigt
|
|
89
|
+
self.value_to_dof = SymmetricTensorMapper.value_to_dof_3d_voigt
|
|
90
|
+
else:
|
|
91
|
+
self.dof_to_value = SymmetricTensorMapper.dof_to_value_3d
|
|
92
|
+
self.value_to_dof = SymmetricTensorMapper.value_to_dof_3d
|
|
93
|
+
else:
|
|
94
|
+
raise ValueError("Unsupported value dtype: ", dtype)
|
|
95
|
+
|
|
96
|
+
def __str__(self):
|
|
97
|
+
return f"{self.mapping}_{self.DOF_SIZE}"
|
|
98
|
+
|
|
99
|
+
@wp.func
|
|
100
|
+
def dof_to_value_2d(dof: wp.vec3):
|
|
101
|
+
a = dof[0]
|
|
102
|
+
b = dof[1]
|
|
103
|
+
c = dof[2]
|
|
104
|
+
return wp.mat22(a + b, c, c, a - b)
|
|
105
|
+
|
|
106
|
+
@wp.func
|
|
107
|
+
def value_to_dof_2d(val: wp.mat22):
|
|
108
|
+
a = 0.5 * (val[0, 0] + val[1, 1])
|
|
109
|
+
b = 0.5 * (val[0, 0] - val[1, 1])
|
|
110
|
+
c = 0.5 * (val[0, 1] + val[1, 0])
|
|
111
|
+
return wp.vec3(a, b, c)
|
|
112
|
+
|
|
113
|
+
@wp.func
|
|
114
|
+
def dof_to_value_2d_voigt(dof: wp.vec3):
|
|
115
|
+
a = _SQRT_2 * dof[0]
|
|
116
|
+
b = _SQRT_2 * dof[1]
|
|
117
|
+
c = dof[2]
|
|
118
|
+
return wp.mat22(a, c, c, b)
|
|
119
|
+
|
|
120
|
+
@wp.func
|
|
121
|
+
def value_to_dof_2d_voigt(val: wp.mat22):
|
|
122
|
+
a = _SQRT_1_2 * val[0, 0]
|
|
123
|
+
b = _SQRT_1_2 * val[1, 1]
|
|
124
|
+
c = 0.5 * (val[0, 1] + val[1, 0])
|
|
125
|
+
return wp.vec3(a, b, c)
|
|
126
|
+
|
|
127
|
+
@wp.func
|
|
128
|
+
def dof_to_value_3d(dof: vec6):
|
|
129
|
+
a = dof[0] * _SQRT_2 * _SQRT_1_3
|
|
130
|
+
b = dof[1]
|
|
131
|
+
c = dof[2] * _SQRT_1_3
|
|
132
|
+
d = dof[3]
|
|
133
|
+
e = dof[4]
|
|
134
|
+
f = dof[5]
|
|
135
|
+
return wp.mat33(
|
|
136
|
+
a + b - c,
|
|
137
|
+
f,
|
|
138
|
+
e,
|
|
139
|
+
f,
|
|
140
|
+
a - b - c,
|
|
141
|
+
d,
|
|
142
|
+
e,
|
|
143
|
+
d,
|
|
144
|
+
a + 2.0 * c,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
@wp.func
|
|
148
|
+
def value_to_dof_3d(val: wp.mat33):
|
|
149
|
+
a = (val[0, 0] + val[1, 1] + val[2, 2]) * _SQRT_1_3 * _SQRT_1_2
|
|
150
|
+
b = 0.5 * (val[0, 0] - val[1, 1])
|
|
151
|
+
c = 0.5 * (val[2, 2] - (val[0, 0] + val[1, 1] + val[2, 2]) / 3.0) * _SQRT_3
|
|
152
|
+
|
|
153
|
+
d = 0.5 * (val[2, 1] + val[1, 2])
|
|
154
|
+
e = 0.5 * (val[0, 2] + val[2, 0])
|
|
155
|
+
f = 0.5 * (val[1, 0] + val[0, 1])
|
|
156
|
+
|
|
157
|
+
return vec6(a, b, c, d, e, f)
|
|
158
|
+
|
|
159
|
+
@wp.func
|
|
160
|
+
def dof_to_value_3d_voigt(dof: vec6):
|
|
161
|
+
a = _SQRT_2 * dof[0]
|
|
162
|
+
b = _SQRT_2 * dof[1]
|
|
163
|
+
c = _SQRT_2 * dof[2]
|
|
164
|
+
d = dof[3]
|
|
165
|
+
e = dof[4]
|
|
166
|
+
f = dof[5]
|
|
167
|
+
return wp.mat33(
|
|
168
|
+
a,
|
|
169
|
+
f,
|
|
170
|
+
e,
|
|
171
|
+
f,
|
|
172
|
+
b,
|
|
173
|
+
d,
|
|
174
|
+
e,
|
|
175
|
+
d,
|
|
176
|
+
c,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
@wp.func
|
|
180
|
+
def value_to_dof_3d_voigt(val: wp.mat33):
|
|
181
|
+
a = _SQRT_1_2 * val[0, 0]
|
|
182
|
+
b = _SQRT_1_2 * val[1, 1]
|
|
183
|
+
c = _SQRT_1_2 * val[2, 2]
|
|
184
|
+
|
|
185
|
+
d = 0.5 * (val[2, 1] + val[1, 2])
|
|
186
|
+
e = 0.5 * (val[0, 2] + val[2, 0])
|
|
187
|
+
f = 0.5 * (val[1, 0] + val[0, 1])
|
|
188
|
+
|
|
189
|
+
return vec6(a, b, c, d, e, f)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class SkewSymmetricTensorMapper(DofMapper):
|
|
193
|
+
"""Orthonormal isomorphism from R^{n (n-1)} to nxn skew-symmetric tensors,
|
|
194
|
+
using usual L2 norm for vectors and half Frobenius norm, (tau : tau)/2 for tensors.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
def __init__(self, dtype: type):
|
|
198
|
+
self.value_dtype = dtype
|
|
199
|
+
|
|
200
|
+
if dtype == wp.mat22:
|
|
201
|
+
self.dof_dtype = float
|
|
202
|
+
self.DOF_SIZE = wp.constant(1)
|
|
203
|
+
self.dof_to_value = SkewSymmetricTensorMapper.dof_to_value_2d
|
|
204
|
+
self.value_to_dof = SkewSymmetricTensorMapper.value_to_dof_2d
|
|
205
|
+
elif dtype == wp.mat33:
|
|
206
|
+
self.dof_dtype = wp.vec3
|
|
207
|
+
self.DOF_SIZE = wp.constant(3)
|
|
208
|
+
self.dof_to_value = SkewSymmetricTensorMapper.dof_to_value_3d
|
|
209
|
+
self.value_to_dof = SkewSymmetricTensorMapper.value_to_dof_3d
|
|
210
|
+
else:
|
|
211
|
+
raise ValueError("Unsupported value dtype: ", dtype)
|
|
212
|
+
|
|
213
|
+
def __str__(self):
|
|
214
|
+
return f"{self.__class__.__name__}_{self.DOF_SIZE}"
|
|
215
|
+
|
|
216
|
+
@wp.func
|
|
217
|
+
def dof_to_value_2d(dof: float):
|
|
218
|
+
return wp.mat22(0.0, -dof, dof, 0.0)
|
|
219
|
+
|
|
220
|
+
@wp.func
|
|
221
|
+
def value_to_dof_2d(val: wp.mat22):
|
|
222
|
+
return 0.5 * (val[1, 0] - val[0, 1])
|
|
223
|
+
|
|
224
|
+
@wp.func
|
|
225
|
+
def dof_to_value_3d(dof: wp.vec3):
|
|
226
|
+
a = dof[0]
|
|
227
|
+
b = dof[1]
|
|
228
|
+
c = dof[2]
|
|
229
|
+
return wp.mat33(0.0, -c, b, c, 0.0, -a, -b, a, 0.0)
|
|
230
|
+
|
|
231
|
+
@wp.func
|
|
232
|
+
def value_to_dof_3d(val: wp.mat33):
|
|
233
|
+
a = 0.5 * (val[2, 1] - val[1, 2])
|
|
234
|
+
b = 0.5 * (val[0, 2] - val[2, 0])
|
|
235
|
+
c = 0.5 * (val[1, 0] - val[0, 1])
|
|
236
|
+
return wp.vec3(a, b, c)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import warp as wp
|
|
4
|
+
|
|
5
|
+
from warp.fem.types import DofIndex, ElementIndex, Coords
|
|
6
|
+
from warp.fem.geometry import Geometry
|
|
7
|
+
|
|
8
|
+
from .topology import SpaceTopology
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FunctionSpace:
|
|
12
|
+
"""
|
|
13
|
+
Interface class for function spaces, i.e. geometry + interpolation basis
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
dtype: type
|
|
17
|
+
"""Value type of the interpolation functions"""
|
|
18
|
+
|
|
19
|
+
SpaceArg: wp.codegen.Struct
|
|
20
|
+
"""Structure containing arguments to be passed to device function"""
|
|
21
|
+
|
|
22
|
+
VALUE_DOF_COUNT: int
|
|
23
|
+
"""Number of degrees of freedom per node, as a Warp constant"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, topology: SpaceTopology):
|
|
26
|
+
self._topology = topology
|
|
27
|
+
|
|
28
|
+
if self._topology.is_trace:
|
|
29
|
+
self.element_inner_reference_gradient_transform = self.geometry.side_inner_inverse_deformation_gradient
|
|
30
|
+
self.element_outer_reference_gradient_transform = self.geometry.side_outer_inverse_deformation_gradient
|
|
31
|
+
else:
|
|
32
|
+
self.element_inner_reference_gradient_transform = self.geometry.cell_inverse_deformation_gradient
|
|
33
|
+
self.element_outer_reference_gradient_transform = self.geometry.cell_inverse_deformation_gradient
|
|
34
|
+
|
|
35
|
+
def node_count(self) -> int:
|
|
36
|
+
"""Number of nodes in the interpolation basis"""
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
|
|
39
|
+
def space_arg_value(self, device) -> wp.codegen.StructInstance:
|
|
40
|
+
"""Value of the arguments to be passed to device functions"""
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def topology(self) -> SpaceTopology:
|
|
45
|
+
"""Underlying geometry"""
|
|
46
|
+
return self._topology
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def geometry(self) -> Geometry:
|
|
50
|
+
"""Underlying geometry"""
|
|
51
|
+
return self.topology.geometry
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def dimension(self) -> int:
|
|
55
|
+
"""Function space embedding dimension"""
|
|
56
|
+
return self.topology.dimension
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def degree(self) -> int:
|
|
60
|
+
"""Maximum polynomial degree of the underlying basis"""
|
|
61
|
+
raise NotImplementedError
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def name(self):
|
|
65
|
+
raise NotImplementedError
|
|
66
|
+
|
|
67
|
+
def __str__(self):
|
|
68
|
+
return self.name
|
|
69
|
+
|
|
70
|
+
def trace(self) -> "FunctionSpace":
|
|
71
|
+
"""Trace of the function space over lower-dimensional elements of the geometry"""
|
|
72
|
+
raise NotImplementedError
|
|
73
|
+
|
|
74
|
+
def make_field(self, space_partition=None):
|
|
75
|
+
"""Creates a zero-initialized discrete field over the function space holding values for all degrees of freedom of nodes in a space partition
|
|
76
|
+
|
|
77
|
+
space_arg:
|
|
78
|
+
space_partition: If provided, the subset of nodes to consider
|
|
79
|
+
|
|
80
|
+
See also: :func:`make_space_partition`
|
|
81
|
+
"""
|
|
82
|
+
raise NotImplementedError
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def unit_dof_value(elt_arg: "SpaceTopology.ElementArg", space_arg: "SpaceArg", dof: DofIndex):
|
|
86
|
+
"""Unit value for a given degree of freedom. Typically a rank-1 tensor"""
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def node_coords_in_element(
|
|
91
|
+
elt_arg: "SpaceTopology.ElementArg", space_arg: "SpaceArg", element_index: ElementIndex, node_index_in_elt: int
|
|
92
|
+
):
|
|
93
|
+
"""Coordinates inside element of a given node"""
|
|
94
|
+
raise NotImplementedError
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def node_quadrature_weight(
|
|
98
|
+
elt_arg: "SpaceTopology.ElementArg", space_arg: "SpaceArg", element_index: ElementIndex, node_index_in_elt: int
|
|
99
|
+
):
|
|
100
|
+
"""Weight of a given node when used as a quadrature point"""
|
|
101
|
+
raise NotImplementedError
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def element_inner_weight(
|
|
105
|
+
elt_arg: "SpaceTopology.ElementArg",
|
|
106
|
+
space_arg: "SpaceArg",
|
|
107
|
+
element_index: ElementIndex,
|
|
108
|
+
coords: Coords,
|
|
109
|
+
node_index_in_elt: int,
|
|
110
|
+
):
|
|
111
|
+
"""Inner weight for a node at given coordinates"""
|
|
112
|
+
raise NotImplementedError
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def element_inner_weight_gradient(
|
|
116
|
+
elt_arg: "SpaceTopology.ElementArg",
|
|
117
|
+
space_arg: "SpaceArg",
|
|
118
|
+
element_index: ElementIndex,
|
|
119
|
+
coords: Coords,
|
|
120
|
+
node_index_in_elt: int,
|
|
121
|
+
):
|
|
122
|
+
"""Inner weight gradient w.r.t. reference space for a node at given coordinates"""
|
|
123
|
+
raise NotImplementedError
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def element_outer_weight(
|
|
127
|
+
elt_arg: "SpaceTopology.ElementArg",
|
|
128
|
+
space_arg: "SpaceArg",
|
|
129
|
+
element_index: ElementIndex,
|
|
130
|
+
coords: Coords,
|
|
131
|
+
node_index_in_elt: int,
|
|
132
|
+
):
|
|
133
|
+
"""Outer weight for a node at given coordinates"""
|
|
134
|
+
raise NotImplementedError
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def element_outer_weight_gradient(
|
|
138
|
+
elt_arg: "SpaceTopology.ElementArg",
|
|
139
|
+
space_arg: "SpaceArg",
|
|
140
|
+
element_index: ElementIndex,
|
|
141
|
+
coords: Coords,
|
|
142
|
+
node_index_in_elt: int,
|
|
143
|
+
):
|
|
144
|
+
"""Outer weight gradient w.r.t reference space for a node at given coordinates"""
|
|
145
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import warp as wp
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from warp.fem.types import ElementIndex, Coords
|
|
5
|
+
from warp.fem.polynomial import Polynomial, is_closed
|
|
6
|
+
from warp.fem.geometry import Grid2D
|
|
7
|
+
from warp.fem import cache
|
|
8
|
+
|
|
9
|
+
from .topology import SpaceTopology, DiscontinuousSpaceTopologyMixin, forward_base_topology
|
|
10
|
+
from .basis_space import ShapeBasisSpace, TraceBasisSpace
|
|
11
|
+
|
|
12
|
+
from .shape import ShapeFunction, ConstantShapeFunction
|
|
13
|
+
from .shape import (
|
|
14
|
+
SquareBipolynomialShapeFunctions,
|
|
15
|
+
SquareSerendipityShapeFunctions,
|
|
16
|
+
SquareNonConformingPolynomialShapeFunctions,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Grid2DSpaceTopology(SpaceTopology):
|
|
21
|
+
def __init__(self, grid: Grid2D, shape: ShapeFunction):
|
|
22
|
+
super().__init__(grid, shape.NODES_PER_ELEMENT)
|
|
23
|
+
self._shape = shape
|
|
24
|
+
|
|
25
|
+
@wp.func
|
|
26
|
+
def _vertex_coords(vidx_in_cell: int):
|
|
27
|
+
x = vidx_in_cell // 2
|
|
28
|
+
y = vidx_in_cell - 2 * x
|
|
29
|
+
return wp.vec2i(x, y)
|
|
30
|
+
|
|
31
|
+
@wp.func
|
|
32
|
+
def _vertex_index(cell_arg: Grid2D.CellArg, cell_index: ElementIndex, vidx_in_cell: int):
|
|
33
|
+
res = cell_arg.res
|
|
34
|
+
x_stride = res[1] + 1
|
|
35
|
+
|
|
36
|
+
corner = Grid2D.get_cell(res, cell_index) + Grid2DSpaceTopology._vertex_coords(vidx_in_cell)
|
|
37
|
+
return Grid2D._from_2d_index(x_stride, corner)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Grid2DDiscontinuousSpaceTopology(
|
|
41
|
+
DiscontinuousSpaceTopologyMixin,
|
|
42
|
+
Grid2DSpaceTopology,
|
|
43
|
+
):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Grid2DBasisSpace(ShapeBasisSpace):
|
|
48
|
+
def __init__(self, topology: Grid2DSpaceTopology, shape: ShapeFunction):
|
|
49
|
+
super().__init__(topology, shape)
|
|
50
|
+
|
|
51
|
+
self._grid: Grid2D = topology.geometry
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class GridPiecewiseConstantBasis(Grid2DBasisSpace):
|
|
55
|
+
def __init__(self, grid: Grid2D):
|
|
56
|
+
shape = ConstantShapeFunction(grid.reference_cell(), space_dimension=2)
|
|
57
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape)
|
|
58
|
+
super().__init__(shape=shape, topology=topology)
|
|
59
|
+
|
|
60
|
+
if isinstance(grid, Grid2D):
|
|
61
|
+
self.node_grid = self._node_grid
|
|
62
|
+
|
|
63
|
+
def _node_grid(self):
|
|
64
|
+
res = self._grid.res
|
|
65
|
+
|
|
66
|
+
X = (np.arange(0, res[0], dtype=float) + 0.5) * self._grid.cell_size[0] + self._grid.origin[0]
|
|
67
|
+
Y = (np.arange(0, res[1], dtype=float) + 0.5) * self._grid.cell_size[1] + self._grid.origin[1]
|
|
68
|
+
return np.meshgrid(X, Y, indexing="ij")
|
|
69
|
+
|
|
70
|
+
class Trace(TraceBasisSpace):
|
|
71
|
+
@wp.func
|
|
72
|
+
def _node_coords_in_element(
|
|
73
|
+
side_arg: Grid2D.SideArg,
|
|
74
|
+
basis_arg: Grid2DBasisSpace.BasisArg,
|
|
75
|
+
element_index: ElementIndex,
|
|
76
|
+
node_index_in_element: int,
|
|
77
|
+
):
|
|
78
|
+
return Coords(0.5, 0.0, 0.0)
|
|
79
|
+
|
|
80
|
+
def make_node_coords_in_element(self):
|
|
81
|
+
return self._node_coords_in_element
|
|
82
|
+
|
|
83
|
+
def trace(self):
|
|
84
|
+
return GridPiecewiseConstantBasis.Trace(self)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class GridBipolynomialSpaceTopology(Grid2DSpaceTopology):
|
|
88
|
+
def __init__(self, grid: Grid2D, shape: SquareBipolynomialShapeFunctions):
|
|
89
|
+
super().__init__(grid, shape)
|
|
90
|
+
|
|
91
|
+
self.element_node_index = self._make_element_node_index()
|
|
92
|
+
|
|
93
|
+
def node_count(self) -> int:
|
|
94
|
+
return (self.geometry.res[0] * self._shape.ORDER + 1) * (self.geometry.res[1] * self._shape.ORDER + 1)
|
|
95
|
+
|
|
96
|
+
def _make_element_node_index(self):
|
|
97
|
+
ORDER = self._shape.ORDER
|
|
98
|
+
|
|
99
|
+
@cache.dynamic_func(suffix=self.name)
|
|
100
|
+
def element_node_index(
|
|
101
|
+
cell_arg: Grid2D.CellArg,
|
|
102
|
+
topo_arg: Grid2DSpaceTopology.TopologyArg,
|
|
103
|
+
element_index: ElementIndex,
|
|
104
|
+
node_index_in_elt: int,
|
|
105
|
+
):
|
|
106
|
+
res = cell_arg.res
|
|
107
|
+
cell = Grid2D.get_cell(res, element_index)
|
|
108
|
+
|
|
109
|
+
node_i = node_index_in_elt // (ORDER + 1)
|
|
110
|
+
node_j = node_index_in_elt - (ORDER + 1) * node_i
|
|
111
|
+
|
|
112
|
+
node_x = ORDER * cell[0] + node_i
|
|
113
|
+
node_y = ORDER * cell[1] + node_j
|
|
114
|
+
|
|
115
|
+
node_pitch = (res[1] * ORDER) + 1
|
|
116
|
+
node_index = node_pitch * node_x + node_y
|
|
117
|
+
|
|
118
|
+
return node_index
|
|
119
|
+
|
|
120
|
+
return element_node_index
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class GridBipolynomialBasisSpace(Grid2DBasisSpace):
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
grid: Grid2D,
|
|
127
|
+
degree: int,
|
|
128
|
+
family: Polynomial,
|
|
129
|
+
):
|
|
130
|
+
if family is None:
|
|
131
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
132
|
+
|
|
133
|
+
if not is_closed(family):
|
|
134
|
+
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
135
|
+
|
|
136
|
+
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
137
|
+
topology = forward_base_topology(GridBipolynomialSpaceTopology, grid, shape)
|
|
138
|
+
|
|
139
|
+
super().__init__(topology, shape)
|
|
140
|
+
|
|
141
|
+
if isinstance(grid, Grid2D):
|
|
142
|
+
self.node_grid = self._node_grid
|
|
143
|
+
|
|
144
|
+
def _node_grid(self):
|
|
145
|
+
res = self._grid.res
|
|
146
|
+
|
|
147
|
+
cell_coords = np.array(self._shape.LOBATTO_COORDS)[:-1]
|
|
148
|
+
|
|
149
|
+
grid_coords_x = np.repeat(np.arange(0, res[0], dtype=float), len(cell_coords)) + np.tile(
|
|
150
|
+
cell_coords, reps=res[0]
|
|
151
|
+
)
|
|
152
|
+
grid_coords_x = np.append(grid_coords_x, res[0])
|
|
153
|
+
X = grid_coords_x * self._grid.cell_size[0] + self._grid.origin[0]
|
|
154
|
+
|
|
155
|
+
grid_coords_y = np.repeat(np.arange(0, res[1], dtype=float), len(cell_coords)) + np.tile(
|
|
156
|
+
cell_coords, reps=res[1]
|
|
157
|
+
)
|
|
158
|
+
grid_coords_y = np.append(grid_coords_y, res[1])
|
|
159
|
+
Y = grid_coords_y * self._grid.cell_size[1] + self._grid.origin[1]
|
|
160
|
+
|
|
161
|
+
return np.meshgrid(X, Y, indexing="ij")
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class GridDGBipolynomialBasisSpace(Grid2DBasisSpace):
|
|
165
|
+
def __init__(
|
|
166
|
+
self,
|
|
167
|
+
grid: Grid2D,
|
|
168
|
+
degree: int,
|
|
169
|
+
family: Polynomial,
|
|
170
|
+
):
|
|
171
|
+
if family is None:
|
|
172
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
173
|
+
|
|
174
|
+
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
175
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape)
|
|
176
|
+
|
|
177
|
+
super().__init__(shape=shape, topology=topology)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class GridSerendipitySpaceTopology(Grid2DSpaceTopology):
|
|
181
|
+
def __init__(self, grid: Grid2D, shape: SquareSerendipityShapeFunctions):
|
|
182
|
+
super().__init__(grid, shape)
|
|
183
|
+
|
|
184
|
+
self.element_node_index = self._make_element_node_index()
|
|
185
|
+
|
|
186
|
+
TopologyArg = Grid2D.SideArg
|
|
187
|
+
|
|
188
|
+
def topo_arg_value(self, device):
|
|
189
|
+
return self.geometry.side_arg_value(device)
|
|
190
|
+
|
|
191
|
+
def node_count(self) -> int:
|
|
192
|
+
return self.geometry.vertex_count() + (self._shape.ORDER - 1) * self.geometry.side_count()
|
|
193
|
+
|
|
194
|
+
def _make_element_node_index(self):
|
|
195
|
+
ORDER = self._shape.ORDER
|
|
196
|
+
|
|
197
|
+
@cache.dynamic_func(suffix=self.name)
|
|
198
|
+
def element_node_index(
|
|
199
|
+
cell_arg: Grid2D.CellArg,
|
|
200
|
+
topo_arg: Grid2D.SideArg,
|
|
201
|
+
element_index: ElementIndex,
|
|
202
|
+
node_index_in_elt: int,
|
|
203
|
+
):
|
|
204
|
+
node_type, type_index = self._shape.node_type_and_type_index(node_index_in_elt)
|
|
205
|
+
|
|
206
|
+
if node_type == SquareSerendipityShapeFunctions.VERTEX:
|
|
207
|
+
return Grid2DSpaceTopology._vertex_index(cell_arg, element_index, type_index)
|
|
208
|
+
|
|
209
|
+
side_offset, index_in_side = SquareSerendipityShapeFunctions.side_offset_and_index(type_index)
|
|
210
|
+
axis = 1 - (node_type - SquareSerendipityShapeFunctions.EDGE_X)
|
|
211
|
+
|
|
212
|
+
cell = Grid2D.get_cell(cell_arg.res, element_index)
|
|
213
|
+
origin = wp.vec2i(cell[Grid2D.ROTATION[axis, 0]] + side_offset, cell[Grid2D.ROTATION[axis, 1]])
|
|
214
|
+
|
|
215
|
+
side = Grid2D.Side(axis, origin)
|
|
216
|
+
side_index = Grid2D.side_index(topo_arg, side)
|
|
217
|
+
|
|
218
|
+
res = cell_arg.res
|
|
219
|
+
vertex_count = (res[0] + 1) * (res[1] + 1)
|
|
220
|
+
|
|
221
|
+
return vertex_count + (ORDER - 1) * side_index + index_in_side
|
|
222
|
+
|
|
223
|
+
return element_node_index
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class GridSerendipityBasisSpace(Grid2DBasisSpace):
|
|
227
|
+
def __init__(
|
|
228
|
+
self,
|
|
229
|
+
grid: Grid2D,
|
|
230
|
+
degree: int,
|
|
231
|
+
family: Polynomial,
|
|
232
|
+
):
|
|
233
|
+
if family is None:
|
|
234
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
235
|
+
|
|
236
|
+
shape = SquareSerendipityShapeFunctions(degree, family=family)
|
|
237
|
+
topology = forward_base_topology(GridSerendipitySpaceTopology, grid, shape=shape)
|
|
238
|
+
|
|
239
|
+
super().__init__(topology=topology, shape=shape)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
class GridDGSerendipityBasisSpace(Grid2DBasisSpace):
|
|
243
|
+
def __init__(
|
|
244
|
+
self,
|
|
245
|
+
grid: Grid2D,
|
|
246
|
+
degree: int,
|
|
247
|
+
family: Polynomial,
|
|
248
|
+
):
|
|
249
|
+
if family is None:
|
|
250
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
251
|
+
|
|
252
|
+
shape = SquareSerendipityShapeFunctions(degree, family=family)
|
|
253
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape=shape)
|
|
254
|
+
|
|
255
|
+
super().__init__(topology=topology, shape=shape)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class GridDGPolynomialBasisSpace(Grid2DBasisSpace):
|
|
259
|
+
def __init__(
|
|
260
|
+
self,
|
|
261
|
+
grid: Grid2D,
|
|
262
|
+
degree: int,
|
|
263
|
+
):
|
|
264
|
+
shape = SquareNonConformingPolynomialShapeFunctions(degree)
|
|
265
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape=shape)
|
|
266
|
+
|
|
267
|
+
super().__init__(topology=topology, shape=shape)
|