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