warp-lang 1.4.1__py3-none-macosx_10_13_universal2.whl → 1.5.0__py3-none-macosx_10_13_universal2.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 +4 -0
- warp/autograd.py +43 -8
- warp/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +21 -2
- warp/build_dll.py +23 -6
- warp/builtins.py +1920 -111
- warp/codegen.py +186 -62
- warp/config.py +2 -2
- warp/context.py +322 -73
- warp/examples/assets/pixel.jpg +0 -0
- warp/examples/benchmarks/benchmark_cloth_paddle.py +86 -0
- warp/examples/benchmarks/benchmark_gemm.py +121 -0
- warp/examples/benchmarks/benchmark_interop_paddle.py +158 -0
- warp/examples/benchmarks/benchmark_tile.py +179 -0
- warp/examples/core/example_dem.py +2 -1
- warp/examples/core/example_mesh_intersect.py +3 -3
- warp/examples/fem/example_adaptive_grid.py +37 -10
- warp/examples/fem/example_apic_fluid.py +3 -2
- warp/examples/fem/example_convection_diffusion_dg.py +4 -5
- warp/examples/fem/example_deformed_geometry.py +1 -1
- warp/examples/fem/example_diffusion_3d.py +47 -4
- warp/examples/fem/example_distortion_energy.py +220 -0
- warp/examples/fem/example_magnetostatics.py +127 -85
- warp/examples/fem/example_nonconforming_contact.py +5 -5
- warp/examples/fem/example_stokes.py +3 -1
- warp/examples/fem/example_streamlines.py +12 -19
- warp/examples/fem/utils.py +38 -15
- warp/examples/optim/example_walker.py +2 -2
- warp/examples/sim/example_cloth.py +2 -25
- warp/examples/sim/example_jacobian_ik.py +6 -2
- warp/examples/sim/example_quadruped.py +2 -1
- warp/examples/tile/example_tile_convolution.py +58 -0
- warp/examples/tile/example_tile_fft.py +47 -0
- warp/examples/tile/example_tile_filtering.py +105 -0
- warp/examples/tile/example_tile_matmul.py +79 -0
- warp/examples/tile/example_tile_mlp.py +375 -0
- warp/fem/__init__.py +8 -0
- warp/fem/cache.py +16 -12
- warp/fem/dirichlet.py +1 -1
- warp/fem/domain.py +44 -1
- warp/fem/field/__init__.py +1 -2
- warp/fem/field/field.py +31 -19
- warp/fem/field/nodal_field.py +101 -49
- warp/fem/field/virtual.py +794 -0
- warp/fem/geometry/__init__.py +2 -2
- warp/fem/geometry/deformed_geometry.py +3 -105
- warp/fem/geometry/element.py +13 -0
- warp/fem/geometry/geometry.py +165 -5
- warp/fem/geometry/grid_2d.py +3 -6
- warp/fem/geometry/grid_3d.py +31 -28
- warp/fem/geometry/hexmesh.py +3 -46
- warp/fem/geometry/nanogrid.py +3 -2
- warp/fem/geometry/{quadmesh_2d.py → quadmesh.py} +280 -159
- warp/fem/geometry/tetmesh.py +2 -43
- warp/fem/geometry/{trimesh_2d.py → trimesh.py} +354 -186
- warp/fem/integrate.py +683 -261
- warp/fem/linalg.py +404 -0
- warp/fem/operator.py +101 -18
- warp/fem/polynomial.py +5 -5
- warp/fem/quadrature/quadrature.py +45 -21
- warp/fem/space/__init__.py +45 -11
- warp/fem/space/basis_function_space.py +451 -0
- warp/fem/space/basis_space.py +58 -11
- warp/fem/space/function_space.py +146 -5
- warp/fem/space/grid_2d_function_space.py +80 -66
- warp/fem/space/grid_3d_function_space.py +113 -68
- warp/fem/space/hexmesh_function_space.py +96 -108
- warp/fem/space/nanogrid_function_space.py +62 -110
- warp/fem/space/quadmesh_function_space.py +208 -0
- warp/fem/space/shape/__init__.py +45 -7
- warp/fem/space/shape/cube_shape_function.py +328 -54
- warp/fem/space/shape/shape_function.py +10 -1
- warp/fem/space/shape/square_shape_function.py +328 -60
- warp/fem/space/shape/tet_shape_function.py +269 -19
- warp/fem/space/shape/triangle_shape_function.py +238 -19
- warp/fem/space/tetmesh_function_space.py +69 -37
- warp/fem/space/topology.py +38 -0
- warp/fem/space/trimesh_function_space.py +179 -0
- warp/fem/utils.py +6 -331
- warp/jax_experimental.py +3 -1
- warp/native/array.h +55 -40
- warp/native/builtin.h +124 -43
- warp/native/bvh.h +4 -0
- warp/native/coloring.cpp +600 -0
- warp/native/cuda_util.cpp +14 -0
- warp/native/cuda_util.h +2 -1
- warp/native/fabric.h +8 -0
- warp/native/hashgrid.h +4 -0
- warp/native/marching.cu +8 -0
- warp/native/mat.h +14 -3
- warp/native/mathdx.cpp +59 -0
- warp/native/mesh.h +4 -0
- warp/native/range.h +13 -1
- warp/native/reduce.cpp +9 -1
- warp/native/reduce.cu +7 -0
- warp/native/runlength_encode.cpp +9 -1
- warp/native/runlength_encode.cu +7 -1
- warp/native/scan.cpp +8 -0
- warp/native/scan.cu +8 -0
- warp/native/scan.h +8 -1
- warp/native/sparse.cpp +8 -0
- warp/native/sparse.cu +8 -0
- warp/native/temp_buffer.h +7 -0
- warp/native/tile.h +1857 -0
- warp/native/tile_gemm.h +341 -0
- warp/native/tile_reduce.h +210 -0
- warp/native/volume_builder.cu +8 -0
- warp/native/volume_builder.h +8 -0
- warp/native/warp.cpp +10 -2
- warp/native/warp.cu +369 -15
- warp/native/warp.h +12 -2
- warp/optim/adam.py +39 -4
- warp/paddle.py +29 -12
- warp/render/render_opengl.py +137 -65
- warp/sim/graph_coloring.py +292 -0
- warp/sim/integrator_euler.py +4 -2
- warp/sim/integrator_featherstone.py +115 -44
- warp/sim/integrator_vbd.py +6 -0
- warp/sim/model.py +90 -17
- warp/stubs.py +651 -85
- warp/tape.py +12 -7
- warp/tests/assets/pixel.npy +0 -0
- warp/tests/aux_test_instancing_gc.py +18 -0
- warp/tests/test_array.py +207 -48
- warp/tests/test_closest_point_edge_edge.py +8 -8
- warp/tests/test_codegen.py +120 -1
- warp/tests/test_codegen_instancing.py +30 -0
- warp/tests/test_collision.py +110 -0
- warp/tests/test_coloring.py +241 -0
- warp/tests/test_context.py +34 -0
- warp/tests/test_examples.py +18 -4
- warp/tests/test_fabricarray.py +33 -0
- warp/tests/test_fem.py +453 -113
- warp/tests/test_func.py +48 -1
- warp/tests/test_generics.py +52 -0
- warp/tests/test_iter.py +68 -0
- warp/tests/test_mat_scalar_ops.py +1 -1
- warp/tests/test_mesh_query_point.py +5 -4
- warp/tests/test_module_hashing.py +23 -0
- warp/tests/test_paddle.py +27 -87
- warp/tests/test_print.py +191 -1
- warp/tests/test_spatial.py +1 -1
- warp/tests/test_tile.py +700 -0
- warp/tests/test_tile_mathdx.py +144 -0
- warp/tests/test_tile_mlp.py +383 -0
- warp/tests/test_tile_reduce.py +374 -0
- warp/tests/test_tile_shared_memory.py +190 -0
- warp/tests/test_vbd.py +12 -20
- warp/tests/test_volume.py +43 -0
- warp/tests/unittest_suites.py +23 -2
- warp/tests/unittest_utils.py +4 -0
- warp/types.py +339 -73
- warp/utils.py +22 -1
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/METADATA +33 -7
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/RECORD +159 -132
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/WHEEL +1 -1
- warp/fem/field/test.py +0 -180
- warp/fem/field/trial.py +0 -183
- warp/fem/space/collocated_function_space.py +0 -102
- warp/fem/space/quadmesh_2d_function_space.py +0 -261
- warp/fem/space/trimesh_2d_function_space.py +0 -153
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/top_level.txt +0 -0
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# grid and the PicQuadrature class.
|
|
13
13
|
###########################################################################
|
|
14
14
|
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
15
17
|
import numpy as np
|
|
16
18
|
|
|
17
19
|
import warp as wp
|
|
@@ -123,7 +125,7 @@ def scalar_vector_multiply(
|
|
|
123
125
|
@wp.kernel
|
|
124
126
|
def scale_transposed_divergence_mat(
|
|
125
127
|
tr_divergence_mat_offsets: wp.array(dtype=int),
|
|
126
|
-
tr_divergence_mat_values: wp.array(dtype=
|
|
128
|
+
tr_divergence_mat_values: wp.array(dtype=Any),
|
|
127
129
|
inv_fraction_int: wp.array(dtype=float),
|
|
128
130
|
):
|
|
129
131
|
# In-place scaling of gradient operator rows with inverse mass
|
|
@@ -203,7 +205,6 @@ class Example:
|
|
|
203
205
|
particle_grid_offset = wp.vec3(self.radius, self.radius, self.radius)
|
|
204
206
|
|
|
205
207
|
# Initialize warp.sim model, spawn particles
|
|
206
|
-
np.random.seed(0)
|
|
207
208
|
builder = wp.sim.ModelBuilder()
|
|
208
209
|
builder.add_particle_grid(
|
|
209
210
|
dim_x=particle_grid_res[0],
|
|
@@ -88,7 +88,7 @@ class Example:
|
|
|
88
88
|
geo,
|
|
89
89
|
discontinuous=True,
|
|
90
90
|
degree=degree,
|
|
91
|
-
family=fem.Polynomial.
|
|
91
|
+
family=fem.Polynomial.LOBATTO_GAUSS_LEGENDRE,
|
|
92
92
|
)
|
|
93
93
|
|
|
94
94
|
# Assemble transport, diffusion and inertia matrices
|
|
@@ -110,23 +110,22 @@ class Example:
|
|
|
110
110
|
|
|
111
111
|
side_test = fem.make_test(space=scalar_space, domain=sides)
|
|
112
112
|
side_trial = fem.make_trial(space=scalar_space, domain=sides)
|
|
113
|
-
|
|
114
|
-
matrix_transport += fem.integrate(
|
|
113
|
+
fem.integrate(
|
|
115
114
|
upwind_transport_form,
|
|
116
115
|
fields={"phi": side_trial, "psi": side_test},
|
|
117
116
|
values={"ang_vel": ang_vel},
|
|
117
|
+
output=matrix_transport,
|
|
118
|
+
add=True,
|
|
118
119
|
)
|
|
119
120
|
|
|
120
121
|
matrix_diffusion = fem.integrate(
|
|
121
122
|
diffusion_form,
|
|
122
123
|
fields={"u": trial, "v": self._test},
|
|
123
124
|
)
|
|
124
|
-
|
|
125
125
|
matrix_diffusion += fem.integrate(
|
|
126
126
|
sip_diffusion_form,
|
|
127
127
|
fields={"phi": side_trial, "psi": side_test},
|
|
128
128
|
)
|
|
129
|
-
|
|
130
129
|
self._matrix = matrix_inertia + matrix_transport + viscosity * matrix_diffusion
|
|
131
130
|
|
|
132
131
|
# Initial condition
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
# and homogeneous Dirichlet boundary conditions other sides.
|
|
17
17
|
###########################################################################
|
|
18
18
|
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
19
21
|
import warp as wp
|
|
20
22
|
import warp.examples.fem.utils as fem_example_utils
|
|
21
23
|
import warp.fem as fem
|
|
@@ -24,7 +26,7 @@ from warp.sparse import bsr_axpy
|
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
@fem.integrand
|
|
27
|
-
def
|
|
29
|
+
def vertical_boundary_projector_form(
|
|
28
30
|
s: fem.Sample,
|
|
29
31
|
domain: fem.Domain,
|
|
30
32
|
u: fem.Field,
|
|
@@ -36,6 +38,18 @@ def vert_boundary_projector_form(
|
|
|
36
38
|
return w * u(s) * v(s)
|
|
37
39
|
|
|
38
40
|
|
|
41
|
+
@fem.integrand
|
|
42
|
+
def y_boundary_projector_form(
|
|
43
|
+
s: fem.Sample,
|
|
44
|
+
domain: fem.Domain,
|
|
45
|
+
u: fem.Field,
|
|
46
|
+
v: fem.Field,
|
|
47
|
+
):
|
|
48
|
+
# Constrain Y edges
|
|
49
|
+
tangent = fem.deformation_gradient(domain, s)
|
|
50
|
+
return wp.abs(tangent[1]) * u(s) * v(s)
|
|
51
|
+
|
|
52
|
+
|
|
39
53
|
class Example:
|
|
40
54
|
def __init__(
|
|
41
55
|
self,
|
|
@@ -77,6 +91,28 @@ class Example:
|
|
|
77
91
|
bounds_hi=bounds_hi,
|
|
78
92
|
)
|
|
79
93
|
self._geo = fem.Nanogrid(volume)
|
|
94
|
+
elif mesh == "tri":
|
|
95
|
+
pos, quad_vtx_indices = fem_example_utils.gen_trimesh(
|
|
96
|
+
res=res,
|
|
97
|
+
bounds_lo=bounds_lo,
|
|
98
|
+
bounds_hi=bounds_hi,
|
|
99
|
+
)
|
|
100
|
+
pos = pos.numpy()
|
|
101
|
+
pos_z = np.cos(3.0 * pos[:, 0]) * np.sin(4.0 * pos[:, 1])
|
|
102
|
+
pos = np.hstack((pos, np.expand_dims(pos_z, axis=1)))
|
|
103
|
+
pos = wp.array(pos, dtype=wp.vec3)
|
|
104
|
+
self._geo = fem.Trimesh3D(quad_vtx_indices, pos)
|
|
105
|
+
elif mesh == "quad":
|
|
106
|
+
pos, quad_vtx_indices = fem_example_utils.gen_quadmesh(
|
|
107
|
+
res=res,
|
|
108
|
+
bounds_lo=bounds_lo,
|
|
109
|
+
bounds_hi=bounds_hi,
|
|
110
|
+
)
|
|
111
|
+
pos = pos.numpy()
|
|
112
|
+
pos_z = np.cos(3.0 * pos[:, 0]) * np.sin(4.0 * pos[:, 1])
|
|
113
|
+
pos = np.hstack((pos, np.expand_dims(pos_z, axis=1)))
|
|
114
|
+
pos = wp.array(pos, dtype=wp.vec3)
|
|
115
|
+
self._geo = fem.Quadmesh3D(quad_vtx_indices, pos)
|
|
80
116
|
else:
|
|
81
117
|
self._geo = fem.Grid3D(
|
|
82
118
|
res=res,
|
|
@@ -108,7 +144,12 @@ class Example:
|
|
|
108
144
|
|
|
109
145
|
bd_test = fem.make_test(space=self._scalar_space, domain=boundary)
|
|
110
146
|
bd_trial = fem.make_trial(space=self._scalar_space, domain=boundary)
|
|
111
|
-
|
|
147
|
+
|
|
148
|
+
# Pick boundary conditions depending on whether our geometry is a 3d surface or a volume
|
|
149
|
+
boundary_projector_form = (
|
|
150
|
+
vertical_boundary_projector_form if self._geo.cell_dimension == 3 else y_boundary_projector_form
|
|
151
|
+
)
|
|
152
|
+
bd_matrix = fem.integrate(boundary_projector_form, fields={"u": bd_trial, "v": bd_test}, nodal=True)
|
|
112
153
|
|
|
113
154
|
# Diffusion form
|
|
114
155
|
trial = fem.make_trial(space=self._scalar_space, domain=domain)
|
|
@@ -146,7 +187,9 @@ if __name__ == "__main__":
|
|
|
146
187
|
parser.add_argument(
|
|
147
188
|
"--boundary_compliance", type=float, default=0.0, help="Dirichlet boundary condition compliance."
|
|
148
189
|
)
|
|
149
|
-
parser.add_argument(
|
|
190
|
+
parser.add_argument(
|
|
191
|
+
"--mesh", choices=("grid", "tet", "hex", "nano", "anano", "tri", "quad"), default="grid", help="Mesh type."
|
|
192
|
+
)
|
|
150
193
|
parser.add_argument(
|
|
151
194
|
"--headless",
|
|
152
195
|
action="store_true",
|
|
@@ -171,4 +214,4 @@ if __name__ == "__main__":
|
|
|
171
214
|
example.render()
|
|
172
215
|
|
|
173
216
|
if not args.headless:
|
|
174
|
-
example.renderer.plot(
|
|
217
|
+
example.renderer.plot()
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example Distortion Energy
|
|
10
|
+
#
|
|
11
|
+
# This example illustrates using a Newton loop to minimize distortion of a
|
|
12
|
+
# 3D surface (u,v) parameterization under a Symmetric Dirichlet energy,
|
|
13
|
+
#
|
|
14
|
+
# E(F) = 1/2 |F|^2 + |F^{-1}|^2
|
|
15
|
+
#
|
|
16
|
+
# with F := dx/du
|
|
17
|
+
###########################################################################
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
import warp as wp
|
|
22
|
+
import warp.examples.fem.utils as fem_example_utils
|
|
23
|
+
import warp.fem as fem
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@fem.integrand
|
|
27
|
+
def distortion_gradient_form(s: fem.Sample, u_cur: fem.Field, v: fem.Field):
|
|
28
|
+
# Symmetric Dirichlet energy gradient (linear form)
|
|
29
|
+
# E = 1/2 (F:F + F^-T:F^-T)
|
|
30
|
+
|
|
31
|
+
F = fem.grad(u_cur, s)
|
|
32
|
+
|
|
33
|
+
F_inv_sq = wp.inverse(F * wp.transpose(F))
|
|
34
|
+
F_inv = F_inv_sq * F
|
|
35
|
+
|
|
36
|
+
dE_dF = F - F_inv_sq * F_inv
|
|
37
|
+
|
|
38
|
+
return wp.ddot(fem.grad(v, s), dE_dF)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@fem.integrand
|
|
42
|
+
def distortion_hessian_form(s: fem.Sample, u_cur: fem.Field, u: fem.Field, v: fem.Field):
|
|
43
|
+
# Symmetric Dirichlet energy approximate hessian (bilinear form)
|
|
44
|
+
|
|
45
|
+
# F:F term
|
|
46
|
+
H = wp.ddot(fem.grad(v, s), fem.grad(u, s))
|
|
47
|
+
|
|
48
|
+
# F^-T:F^-T term
|
|
49
|
+
F = fem.grad(u_cur, s)
|
|
50
|
+
F_inv_sq = wp.inverse(F * wp.transpose(F))
|
|
51
|
+
|
|
52
|
+
# Gauss--Newton (ignore F^-2 derivative)
|
|
53
|
+
H += wp.ddot(F_inv_sq * fem.grad(v, s), F_inv_sq * F_inv_sq * fem.grad(u, s))
|
|
54
|
+
|
|
55
|
+
return H
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@fem.integrand
|
|
59
|
+
def initial_guess(
|
|
60
|
+
s: fem.Sample,
|
|
61
|
+
domain: fem.Domain,
|
|
62
|
+
):
|
|
63
|
+
# initialization for UV parameter
|
|
64
|
+
x = domain(s)
|
|
65
|
+
return wp.vec2(x[0], x[1])
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@fem.integrand
|
|
69
|
+
def boundary_projector_form(
|
|
70
|
+
s: fem.Sample,
|
|
71
|
+
domain: fem.Domain,
|
|
72
|
+
u: fem.Field,
|
|
73
|
+
v: fem.Field,
|
|
74
|
+
):
|
|
75
|
+
# Fix a single point
|
|
76
|
+
# (underconstrained, solution up to a rotation in UV space)
|
|
77
|
+
w = wp.select(s.qp_index == 0, 0.0, 1.0)
|
|
78
|
+
return w * wp.dot(u(s), v(s))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@fem.integrand
|
|
82
|
+
def checkerboard(s: fem.Sample, domain: fem.Domain, u: fem.Field):
|
|
83
|
+
# checkerboard pattern for parameter visualization
|
|
84
|
+
u_s = u(s)
|
|
85
|
+
return wp.sign(wp.cos(16.0 * u_s[0]) * wp.sin(16.0 * u_s[1]))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Example:
|
|
89
|
+
def __init__(
|
|
90
|
+
self,
|
|
91
|
+
quiet=False,
|
|
92
|
+
degree=2,
|
|
93
|
+
resolution=25,
|
|
94
|
+
mesh="grid",
|
|
95
|
+
nonconforming_stresses=False,
|
|
96
|
+
):
|
|
97
|
+
self._quiet = quiet
|
|
98
|
+
|
|
99
|
+
def deform_along_z(positions, z_scale=1.0):
|
|
100
|
+
pos = positions.numpy()
|
|
101
|
+
pos_z = z_scale * np.cos(3.0 * pos[:, 0]) * np.sin(4.0 * pos[:, 1])
|
|
102
|
+
pos = np.hstack((pos, np.expand_dims(pos_z, axis=1)))
|
|
103
|
+
return wp.array(pos, dtype=wp.vec3)
|
|
104
|
+
|
|
105
|
+
# Grid or mesh geometry
|
|
106
|
+
if mesh == "tri":
|
|
107
|
+
positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(resolution))
|
|
108
|
+
self._uv_geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=wp.zeros_like(positions))
|
|
109
|
+
|
|
110
|
+
positions = deform_along_z(positions)
|
|
111
|
+
self._geo = fem.Trimesh3D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
112
|
+
elif mesh == "quad":
|
|
113
|
+
positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
|
|
114
|
+
self._uv_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=wp.zeros_like(positions))
|
|
115
|
+
|
|
116
|
+
positions = deform_along_z(positions)
|
|
117
|
+
self._geo = fem.Quadmesh3D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
118
|
+
else:
|
|
119
|
+
positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
|
|
120
|
+
self._uv_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=wp.zeros_like(positions))
|
|
121
|
+
|
|
122
|
+
undef_positions = deform_along_z(positions, z_scale=0.0)
|
|
123
|
+
flat_geo = fem.Quadmesh3D(quad_vertex_indices=quad_vidx, positions=undef_positions)
|
|
124
|
+
|
|
125
|
+
deformation_field = fem.make_discrete_field(fem.make_polynomial_space(flat_geo, dtype=wp.vec3))
|
|
126
|
+
deformation_field.dof_values = deform_along_z(positions)
|
|
127
|
+
|
|
128
|
+
self._geo = deformation_field.make_deformed_geometry(relative=False)
|
|
129
|
+
|
|
130
|
+
# parameter space
|
|
131
|
+
self._u_space = fem.make_polynomial_space(self._geo, degree=degree, dtype=wp.vec2)
|
|
132
|
+
self._u_field = self._u_space.make_field()
|
|
133
|
+
self._du_field = self._u_space.make_field()
|
|
134
|
+
fem.interpolate(initial_guess, dest=self._u_field)
|
|
135
|
+
|
|
136
|
+
# scalar parameter visualization function
|
|
137
|
+
viz_space = fem.make_polynomial_space(self._geo, degree=3, dtype=float)
|
|
138
|
+
self.viz_field = viz_space.make_field()
|
|
139
|
+
# For visualization of uv in 2D space
|
|
140
|
+
uv_space = fem.make_polynomial_space(self._uv_geo, degree=degree, dtype=wp.vec2)
|
|
141
|
+
self._uv_field = uv_space.make_field()
|
|
142
|
+
|
|
143
|
+
self.renderer = fem_example_utils.Plot()
|
|
144
|
+
|
|
145
|
+
def step(self):
|
|
146
|
+
boundary = fem.BoundarySides(self._geo)
|
|
147
|
+
domain = fem.Cells(geometry=self._geo)
|
|
148
|
+
|
|
149
|
+
# Parameter boundary conditions
|
|
150
|
+
u_bd_test = fem.make_test(space=self._u_space, domain=boundary)
|
|
151
|
+
u_bd_trial = fem.make_trial(space=self._u_space, domain=boundary)
|
|
152
|
+
u_bd_matrix = fem.integrate(
|
|
153
|
+
boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, nodal=True, output_dtype=float
|
|
154
|
+
)
|
|
155
|
+
fem.normalize_dirichlet_projector(u_bd_matrix)
|
|
156
|
+
|
|
157
|
+
u_test = fem.make_test(space=self._u_space, domain=domain)
|
|
158
|
+
u_trial = fem.make_trial(space=self._u_space, domain=domain)
|
|
159
|
+
|
|
160
|
+
# Newton iterations (without line-search for simplicity)
|
|
161
|
+
for _newton_iteration in range(10):
|
|
162
|
+
u_matrix = fem.integrate(
|
|
163
|
+
distortion_hessian_form, fields={"u_cur": self._u_field, "u": u_trial, "v": u_test}, output_dtype=float
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
u_rhs = fem.integrate(
|
|
167
|
+
distortion_gradient_form, fields={"u_cur": self._u_field, "v": u_test}, output_dtype=wp.vec2
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
fem.project_linear_system(u_matrix, u_rhs, u_bd_matrix, normalize_projector=False)
|
|
171
|
+
|
|
172
|
+
# Solve for uv increment
|
|
173
|
+
du = self._du_field.dof_values
|
|
174
|
+
du.zero_()
|
|
175
|
+
fem_example_utils.bsr_cg(u_matrix, b=u_rhs, x=du, quiet=self._quiet)
|
|
176
|
+
|
|
177
|
+
# Accumulate to UV field
|
|
178
|
+
fem.utils.array_axpy(x=du, y=self._u_field.dof_values, alpha=-1.0, beta=1.0)
|
|
179
|
+
|
|
180
|
+
def render(self):
|
|
181
|
+
# Visualization
|
|
182
|
+
fem.interpolate(checkerboard, fields={"u": self._u_field}, dest=self.viz_field)
|
|
183
|
+
|
|
184
|
+
self._uv_field.dof_values = wp.clone(self._u_field.dof_values)
|
|
185
|
+
|
|
186
|
+
self.renderer.add_field("pattern", self.viz_field)
|
|
187
|
+
self.renderer.add_field("uv", self._uv_field)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
if __name__ == "__main__":
|
|
191
|
+
import argparse
|
|
192
|
+
|
|
193
|
+
wp.set_module_options({"enable_backward": False})
|
|
194
|
+
|
|
195
|
+
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
196
|
+
parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
|
|
197
|
+
parser.add_argument("--resolution", type=int, default=25, help="Grid resolution.")
|
|
198
|
+
parser.add_argument("--degree", type=int, default=1, help="Polynomial degree of shape functions.")
|
|
199
|
+
parser.add_argument("--mesh", choices=("tri", "quad", "deformed"), default="tri", help="Mesh type")
|
|
200
|
+
parser.add_argument(
|
|
201
|
+
"--headless",
|
|
202
|
+
action="store_true",
|
|
203
|
+
help="Run in headless mode, suppressing the opening of any graphical windows.",
|
|
204
|
+
)
|
|
205
|
+
parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
|
|
206
|
+
|
|
207
|
+
args = parser.parse_known_args()[0]
|
|
208
|
+
|
|
209
|
+
with wp.ScopedDevice(args.device):
|
|
210
|
+
example = Example(
|
|
211
|
+
quiet=args.quiet,
|
|
212
|
+
degree=args.degree,
|
|
213
|
+
resolution=args.resolution,
|
|
214
|
+
mesh=args.mesh,
|
|
215
|
+
)
|
|
216
|
+
example.step()
|
|
217
|
+
example.render()
|
|
218
|
+
|
|
219
|
+
if not args.headless:
|
|
220
|
+
example.renderer.plot(options={"uv": {"displacement": {}}})
|