warp-lang 1.0.0b2__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docs/conf.py +17 -5
- examples/env/env_ant.py +1 -1
- examples/env/env_cartpole.py +1 -1
- examples/env/env_humanoid.py +1 -1
- examples/env/env_usd.py +4 -1
- examples/env/environment.py +8 -9
- examples/example_dem.py +34 -33
- examples/example_diffray.py +364 -337
- examples/example_fluid.py +32 -23
- examples/example_jacobian_ik.py +97 -93
- examples/example_marching_cubes.py +6 -16
- examples/example_mesh.py +6 -16
- examples/example_mesh_intersect.py +16 -14
- examples/example_nvdb.py +14 -16
- examples/example_raycast.py +14 -13
- examples/example_raymarch.py +16 -23
- examples/example_render_opengl.py +19 -10
- examples/example_sim_cartpole.py +82 -78
- examples/example_sim_cloth.py +45 -48
- examples/example_sim_fk_grad.py +51 -44
- examples/example_sim_fk_grad_torch.py +47 -40
- examples/example_sim_grad_bounce.py +108 -133
- examples/example_sim_grad_cloth.py +99 -113
- examples/example_sim_granular.py +5 -6
- examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
- examples/example_sim_neo_hookean.py +51 -55
- examples/example_sim_particle_chain.py +4 -4
- examples/example_sim_quadruped.py +126 -81
- examples/example_sim_rigid_chain.py +54 -61
- examples/example_sim_rigid_contact.py +66 -70
- examples/example_sim_rigid_fem.py +3 -3
- examples/example_sim_rigid_force.py +1 -1
- examples/example_sim_rigid_gyroscopic.py +3 -4
- examples/example_sim_rigid_kinematics.py +28 -39
- examples/example_sim_trajopt.py +112 -110
- examples/example_sph.py +9 -8
- examples/example_wave.py +7 -7
- examples/fem/bsr_utils.py +30 -17
- examples/fem/example_apic_fluid.py +85 -69
- examples/fem/example_convection_diffusion.py +97 -93
- examples/fem/example_convection_diffusion_dg.py +142 -149
- examples/fem/example_convection_diffusion_dg0.py +141 -136
- examples/fem/example_deformed_geometry.py +146 -0
- examples/fem/example_diffusion.py +115 -84
- examples/fem/example_diffusion_3d.py +116 -86
- examples/fem/example_diffusion_mgpu.py +102 -79
- examples/fem/example_mixed_elasticity.py +139 -100
- examples/fem/example_navier_stokes.py +175 -162
- examples/fem/example_stokes.py +143 -111
- examples/fem/example_stokes_transfer.py +186 -157
- examples/fem/mesh_utils.py +59 -97
- examples/fem/plot_utils.py +138 -17
- tools/ci/publishing/build_nodes_info.py +54 -0
- warp/__init__.py +4 -3
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +5 -3
- warp/build_dll.py +29 -9
- warp/builtins.py +836 -492
- warp/codegen.py +864 -553
- warp/config.py +3 -1
- warp/context.py +389 -172
- warp/fem/__init__.py +24 -6
- warp/fem/cache.py +318 -25
- warp/fem/dirichlet.py +7 -3
- warp/fem/domain.py +14 -0
- warp/fem/field/__init__.py +30 -38
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +244 -138
- warp/fem/field/restriction.py +8 -6
- warp/fem/field/test.py +127 -59
- warp/fem/field/trial.py +117 -60
- warp/fem/geometry/__init__.py +5 -1
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +24 -1
- warp/fem/geometry/geometry.py +86 -14
- warp/fem/geometry/grid_2d.py +112 -54
- warp/fem/geometry/grid_3d.py +134 -65
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +85 -33
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +451 -115
- warp/fem/geometry/trimesh_2d.py +197 -92
- warp/fem/integrate.py +534 -268
- warp/fem/operator.py +58 -31
- warp/fem/polynomial.py +11 -0
- warp/fem/quadrature/__init__.py +1 -1
- warp/fem/quadrature/pic_quadrature.py +150 -58
- warp/fem/quadrature/quadrature.py +209 -57
- warp/fem/space/__init__.py +230 -53
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +49 -2
- warp/fem/space/function_space.py +90 -39
- warp/fem/space/grid_2d_function_space.py +149 -496
- warp/fem/space/grid_3d_function_space.py +173 -538
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +129 -76
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +46 -34
- 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 +132 -1039
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +104 -742
- warp/fem/types.py +13 -11
- warp/fem/utils.py +335 -60
- warp/native/array.h +120 -34
- warp/native/builtin.h +101 -72
- warp/native/bvh.cpp +73 -325
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +22 -40
- warp/native/clang/clang.cpp +1 -0
- warp/native/crt.h +2 -0
- warp/native/cuda_util.cpp +8 -3
- warp/native/cuda_util.h +1 -0
- warp/native/exports.h +1522 -1243
- warp/native/intersect.h +19 -4
- warp/native/intersect_adj.h +8 -8
- warp/native/mat.h +76 -17
- warp/native/mesh.cpp +33 -108
- warp/native/mesh.cu +114 -18
- warp/native/mesh.h +395 -40
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +44 -34
- warp/native/reduce.cpp +1 -1
- warp/native/sparse.cpp +4 -4
- warp/native/sparse.cu +163 -155
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +18 -14
- warp/native/vec.h +103 -21
- warp/native/warp.cpp +2 -1
- warp/native/warp.cu +28 -3
- warp/native/warp.h +4 -3
- warp/render/render_opengl.py +261 -109
- warp/sim/__init__.py +1 -2
- warp/sim/articulation.py +385 -185
- warp/sim/import_mjcf.py +59 -48
- warp/sim/import_urdf.py +15 -15
- warp/sim/import_usd.py +174 -102
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_xpbd.py +4 -3
- warp/sim/model.py +330 -250
- warp/sim/render.py +1 -1
- warp/sparse.py +625 -152
- warp/stubs.py +341 -309
- warp/tape.py +9 -6
- 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 +94 -74
- warp/tests/test_array.py +82 -101
- warp/tests/test_array_reduce.py +57 -23
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +22 -12
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +18 -18
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +165 -134
- 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 +237 -0
- warp/tests/test_fabricarray.py +22 -24
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1034 -124
- warp/tests/test_fp16.py +23 -16
- warp/tests/test_func.py +187 -86
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +123 -181
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +35 -34
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +24 -25
- 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_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 +304 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +60 -22
- warp/tests/test_mesh_query_aabb.py +21 -25
- warp/tests/test_mesh_query_point.py +111 -22
- warp/tests/test_mesh_query_ray.py +12 -24
- 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 +90 -86
- warp/tests/test_transient_module.py +10 -12
- warp/tests/test_types.py +363 -0
- warp/tests/test_utils.py +451 -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 +418 -376
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +291 -0
- warp/tests/unittest_utils.py +342 -0
- warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +589 -0
- warp/types.py +622 -211
- warp/utils.py +54 -393
- warp_lang-1.0.0b6.dist-info/METADATA +238 -0
- warp_lang-1.0.0b6.dist-info/RECORD +409 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
- examples/example_cache_management.py +0 -40
- examples/example_multigpu.py +0 -54
- examples/example_struct.py +0 -65
- examples/fem/example_stokes_transfer_3d.py +0 -210
- warp/fem/field/discrete_field.py +0 -80
- warp/fem/space/nodal_function_space.py +0 -233
- warp/tests/test_all.py +0 -223
- 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-1.0.0b2.dist-info/METADATA +0 -26
- warp_lang-1.0.0b2.dist-info/RECORD +0 -378
- /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-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
|
@@ -9,202 +9,195 @@ with upwind transport and Symmetric Interior Penalty
|
|
|
9
9
|
import argparse
|
|
10
10
|
|
|
11
11
|
import warp as wp
|
|
12
|
-
|
|
13
|
-
from warp.fem.types import *
|
|
14
|
-
from warp.fem.geometry import Grid2D, Trimesh2D
|
|
15
|
-
from warp.fem.field import make_test, make_trial
|
|
16
|
-
from warp.fem.space import make_polynomial_space
|
|
17
|
-
from warp.fem.quadrature import RegularQuadrature
|
|
18
|
-
from warp.fem.domain import Cells, Sides
|
|
19
|
-
from warp.fem.integrate import integrate, interpolate
|
|
20
|
-
from warp.fem.polynomial import Polynomial
|
|
21
|
-
from warp.fem.operator import (
|
|
22
|
-
grad,
|
|
23
|
-
integrand,
|
|
24
|
-
jump,
|
|
25
|
-
average,
|
|
26
|
-
normal,
|
|
27
|
-
grad_average,
|
|
28
|
-
measure_ratio,
|
|
29
|
-
degree,
|
|
30
|
-
)
|
|
12
|
+
import warp.fem as fem
|
|
31
13
|
|
|
32
14
|
from warp.sparse import bsr_axpy
|
|
33
15
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
from
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
16
|
+
# Import example utilities
|
|
17
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
18
|
+
try:
|
|
19
|
+
from .bsr_utils import bsr_to_scipy
|
|
20
|
+
from .mesh_utils import gen_trimesh, gen_quadmesh
|
|
21
|
+
from .plot_utils import Plot
|
|
22
|
+
from .example_convection_diffusion import (
|
|
23
|
+
initial_condition,
|
|
24
|
+
velocity,
|
|
25
|
+
inertia_form,
|
|
26
|
+
diffusion_form,
|
|
27
|
+
)
|
|
28
|
+
except ImportError:
|
|
29
|
+
from bsr_utils import bsr_to_scipy
|
|
30
|
+
from mesh_utils import gen_trimesh, gen_quadmesh
|
|
31
|
+
from plot_utils import Plot
|
|
32
|
+
from example_convection_diffusion import (
|
|
33
|
+
initial_condition,
|
|
34
|
+
velocity,
|
|
35
|
+
inertia_form,
|
|
36
|
+
diffusion_form,
|
|
37
|
+
)
|
|
44
38
|
|
|
39
|
+
# Non-SPD system, solve using scipy
|
|
45
40
|
from scipy.sparse.linalg import factorized
|
|
46
41
|
|
|
47
|
-
import matplotlib.pyplot as plt
|
|
48
|
-
import matplotlib.animation as animation
|
|
49
|
-
|
|
50
42
|
|
|
51
43
|
# Standard transport term, on cells' interior
|
|
52
|
-
@integrand
|
|
53
|
-
def transport_form(s: Sample, domain: Domain, phi: Field, psi: Field, ang_vel: float):
|
|
44
|
+
@fem.integrand
|
|
45
|
+
def transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
54
46
|
pos = domain(s)
|
|
55
47
|
vel = velocity(pos, ang_vel)
|
|
56
48
|
|
|
57
|
-
return psi(s) * wp.dot(grad(phi, s), vel)
|
|
49
|
+
return psi(s) * wp.dot(fem.grad(phi, s), vel)
|
|
58
50
|
|
|
59
51
|
|
|
60
52
|
# Upwind flux, on cell sides
|
|
61
|
-
@integrand
|
|
62
|
-
def upwind_transport_form(s: Sample, domain: Domain, phi: Field, psi: Field, ang_vel: float):
|
|
53
|
+
@fem.integrand
|
|
54
|
+
def upwind_transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
63
55
|
pos = domain(s)
|
|
64
56
|
vel = velocity(pos, ang_vel)
|
|
65
|
-
vel_n = wp.dot(vel, normal(domain, s))
|
|
57
|
+
vel_n = wp.dot(vel, fem.normal(domain, s))
|
|
66
58
|
|
|
67
|
-
return jump(phi, s) * (-average(psi, s) * vel_n + 0.5 * jump(psi, s) * wp.abs(vel_n))
|
|
59
|
+
return fem.jump(phi, s) * (-fem.average(psi, s) * vel_n + 0.5 * fem.jump(psi, s) * wp.abs(vel_n))
|
|
68
60
|
|
|
69
61
|
|
|
70
62
|
# Symmetric-Interior-Penalty diffusion term (See Pietro Ern 2012)
|
|
71
|
-
@integrand
|
|
63
|
+
@fem.integrand
|
|
72
64
|
def sip_diffusion_form(
|
|
73
|
-
s: Sample,
|
|
74
|
-
domain: Domain,
|
|
75
|
-
psi: Field,
|
|
76
|
-
phi: Field,
|
|
65
|
+
s: fem.Sample,
|
|
66
|
+
domain: fem.Domain,
|
|
67
|
+
psi: fem.Field,
|
|
68
|
+
phi: fem.Field,
|
|
77
69
|
):
|
|
78
|
-
nor = normal(domain, s)
|
|
79
|
-
penalty = measure_ratio(domain, s) * float(degree(psi) * degree(phi))
|
|
70
|
+
nor = fem.normal(domain, s)
|
|
71
|
+
penalty = fem.measure_ratio(domain, s) * float(fem.degree(psi) * fem.degree(phi))
|
|
80
72
|
|
|
81
|
-
return penalty * jump(phi, s) * jump(psi, s) - (
|
|
82
|
-
wp.dot(grad_average(phi, s), nor) * jump(psi, s)
|
|
73
|
+
return penalty * fem.jump(phi, s) * fem.jump(psi, s) - (
|
|
74
|
+
wp.dot(fem.grad_average(phi, s), nor) * fem.jump(psi, s)
|
|
75
|
+
+ wp.dot(fem.grad_average(psi, s), nor) * fem.jump(phi, s)
|
|
83
76
|
)
|
|
84
77
|
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
def identity(s: Sample, phi: Field):
|
|
88
|
-
return phi(s)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if __name__ == "__main__":
|
|
92
|
-
wp.init()
|
|
93
|
-
wp.set_module_options({"enable_backward": False})
|
|
94
|
-
|
|
79
|
+
class Example:
|
|
95
80
|
parser = argparse.ArgumentParser()
|
|
96
81
|
parser.add_argument("--resolution", type=int, default=50)
|
|
97
82
|
parser.add_argument("--degree", type=int, default=2)
|
|
98
|
-
parser.add_argument("--
|
|
83
|
+
parser.add_argument("--num_frames", type=int, default=100)
|
|
99
84
|
parser.add_argument("--viscosity", type=float, default=0.001)
|
|
100
85
|
parser.add_argument("--ang_vel", type=float, default=1.0)
|
|
101
|
-
parser.add_argument("--
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
86
|
+
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
87
|
+
|
|
88
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
89
|
+
if args is None:
|
|
90
|
+
# Read args from kwargs, add default arg values from parser
|
|
91
|
+
args = argparse.Namespace(**kwargs)
|
|
92
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
93
|
+
self._args = args
|
|
94
|
+
self._quiet = quiet
|
|
95
|
+
|
|
96
|
+
res = args.resolution
|
|
97
|
+
self.sim_dt = 1.0 / (args.ang_vel * res)
|
|
98
|
+
self.current_frame = 0
|
|
99
|
+
|
|
100
|
+
if args.mesh == "tri":
|
|
101
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
|
|
102
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
103
|
+
elif args.mesh == "quad":
|
|
104
|
+
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
|
|
105
|
+
geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
106
|
+
else:
|
|
107
|
+
geo = fem.Grid2D(res=wp.vec2i(args.resolution))
|
|
108
|
+
|
|
109
|
+
domain = fem.Cells(geometry=geo)
|
|
110
|
+
sides = fem.Sides(geo)
|
|
111
|
+
scalar_space = fem.make_polynomial_space(
|
|
112
|
+
geo,
|
|
113
|
+
discontinuous=True,
|
|
114
|
+
degree=args.degree,
|
|
115
|
+
family=fem.Polynomial.GAUSS_LEGENDRE,
|
|
116
|
+
)
|
|
122
117
|
|
|
123
|
-
|
|
124
|
-
phi0 = scalar_space.make_field()
|
|
125
|
-
interpolate(initial_condition, dest=phi0)
|
|
118
|
+
# Assemble transport, diffusion and inertia matrices
|
|
126
119
|
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
self._test = fem.make_test(space=scalar_space, domain=domain)
|
|
121
|
+
trial = fem.make_trial(space=scalar_space, domain=domain)
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
matrix_inertia = fem.integrate(
|
|
124
|
+
inertia_form,
|
|
125
|
+
fields={"phi": trial, "psi": self._test},
|
|
126
|
+
values={"dt": self.sim_dt},
|
|
127
|
+
)
|
|
132
128
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
129
|
+
matrix_transport = fem.integrate(
|
|
130
|
+
transport_form,
|
|
131
|
+
fields={"phi": trial, "psi": self._test},
|
|
132
|
+
values={"ang_vel": args.ang_vel},
|
|
133
|
+
)
|
|
139
134
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
fields={"phi": trial, "psi": test},
|
|
143
|
-
values={"ang_vel": args.ang_vel},
|
|
144
|
-
)
|
|
135
|
+
side_test = fem.make_test(space=scalar_space, domain=sides)
|
|
136
|
+
side_trial = fem.make_trial(space=scalar_space, domain=sides)
|
|
145
137
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
138
|
+
bsr_axpy(
|
|
139
|
+
fem.integrate(
|
|
140
|
+
upwind_transport_form,
|
|
141
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
142
|
+
values={"ang_vel": args.ang_vel},
|
|
143
|
+
),
|
|
144
|
+
y=matrix_transport,
|
|
145
|
+
)
|
|
154
146
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
147
|
+
matrix_diffusion = fem.integrate(
|
|
148
|
+
diffusion_form,
|
|
149
|
+
fields={"u": trial, "v": self._test},
|
|
150
|
+
)
|
|
151
|
+
bsr_axpy(
|
|
152
|
+
fem.integrate(
|
|
153
|
+
sip_diffusion_form,
|
|
154
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
155
|
+
),
|
|
156
|
+
y=matrix_diffusion,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
self._matrix = matrix_inertia
|
|
160
|
+
bsr_axpy(x=matrix_transport, y=self._matrix)
|
|
161
|
+
bsr_axpy(x=matrix_diffusion, y=self._matrix, alpha=args.viscosity)
|
|
162
|
+
|
|
163
|
+
# Compute LU factorization of system matrix
|
|
164
|
+
self._solve_lu = factorized(bsr_to_scipy(self._matrix))
|
|
165
|
+
|
|
166
|
+
# Initial condition
|
|
167
|
+
self._phi_field = scalar_space.make_field()
|
|
168
|
+
fem.interpolate(initial_condition, dest=self._phi_field)
|
|
169
|
+
|
|
170
|
+
self.renderer = Plot(stage)
|
|
171
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
166
172
|
|
|
167
|
-
matrix = matrix_inertia
|
|
168
|
-
bsr_axpy(x=matrix_transport, y=matrix)
|
|
169
|
-
bsr_axpy(x=matrix_diffusion, y=matrix, alpha=args.viscosity)
|
|
170
173
|
|
|
171
|
-
|
|
174
|
+
def update(self):
|
|
175
|
+
self.current_frame += 1
|
|
172
176
|
|
|
173
|
-
|
|
174
|
-
phik = phi0
|
|
175
|
-
for k in range(args.n_frames):
|
|
176
|
-
rhs = integrate(
|
|
177
|
+
rhs = fem.integrate(
|
|
177
178
|
inertia_form,
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
values={"dt": dt},
|
|
179
|
+
fields={"phi": self._phi_field, "psi": self._test},
|
|
180
|
+
values={"dt": self.sim_dt},
|
|
181
181
|
)
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
x = matrix_solve(rhs.numpy().flatten())
|
|
183
|
+
self._phi_field.dof_values = self._solve_lu(rhs.numpy())
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
def render(self):
|
|
186
|
+
self.renderer.begin_frame(time = self.current_frame * self.sim_dt)
|
|
187
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
188
|
+
self.renderer.end_frame()
|
|
188
189
|
|
|
189
|
-
colormesh = plot_surface(phi0)
|
|
190
|
-
ax = colormesh.axes
|
|
191
190
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
if __name__ == "__main__":
|
|
192
|
+
wp.init()
|
|
193
|
+
wp.set_module_options({"enable_backward": False})
|
|
195
194
|
|
|
196
|
-
|
|
197
|
-
ax.clear()
|
|
198
|
-
phik.dof_values = results[i]
|
|
199
|
-
interpolate(identity, fields={"phi": phik}, dest=phi_viz)
|
|
195
|
+
args = Example.parser.parse_args()
|
|
200
196
|
|
|
201
|
-
|
|
197
|
+
example = Example(args=args)
|
|
198
|
+
for k in range(args.num_frames):
|
|
199
|
+
print(f"Frame {k}:")
|
|
200
|
+
example.update()
|
|
201
|
+
example.render()
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
ax.figure,
|
|
205
|
-
animate,
|
|
206
|
-
interval=30,
|
|
207
|
-
blit=False,
|
|
208
|
-
frames=len(results),
|
|
209
|
-
)
|
|
210
|
-
plt.show()
|
|
203
|
+
example.renderer.plot()
|
|
@@ -9,174 +9,179 @@ This example simulates a convection-diffusion PDE using FVM with upwind transpor
|
|
|
9
9
|
import argparse
|
|
10
10
|
|
|
11
11
|
import warp as wp
|
|
12
|
-
|
|
13
|
-
from warp.fem.types import *
|
|
14
|
-
from warp.fem.geometry import Grid2D, Trimesh2D
|
|
15
|
-
from warp.fem.field import make_test, make_trial
|
|
16
|
-
from warp.fem.space import make_polynomial_space
|
|
17
|
-
from warp.fem.quadrature import RegularQuadrature
|
|
18
|
-
from warp.fem.domain import Cells, Sides
|
|
19
|
-
from warp.fem.integrate import integrate, interpolate
|
|
20
|
-
from warp.fem.operator import integrand, jump, average, normal
|
|
12
|
+
import warp.fem as fem
|
|
21
13
|
|
|
22
14
|
from warp.sparse import bsr_mm, bsr_axpy, bsr_transposed
|
|
23
15
|
|
|
24
|
-
from bsr_utils import bsr_to_scipy, invert_diagonal_bsr_mass_matrix
|
|
25
|
-
from plot_utils import plot_surface
|
|
26
|
-
from mesh_utils import gen_trimesh
|
|
27
16
|
|
|
28
|
-
|
|
17
|
+
# Import example utilities
|
|
18
|
+
# Make sure that works both when imported as module and run as standalone file
|
|
19
|
+
try:
|
|
20
|
+
from .bsr_utils import bsr_to_scipy, invert_diagonal_bsr_mass_matrix
|
|
21
|
+
from .plot_utils import Plot
|
|
22
|
+
from .mesh_utils import gen_trimesh, gen_quadmesh
|
|
23
|
+
from .example_convection_diffusion import initial_condition, velocity, inertia_form
|
|
24
|
+
except ImportError:
|
|
25
|
+
from bsr_utils import bsr_to_scipy, invert_diagonal_bsr_mass_matrix
|
|
26
|
+
from plot_utils import Plot
|
|
27
|
+
from mesh_utils import gen_trimesh, gen_quadmesh
|
|
28
|
+
from example_convection_diffusion import initial_condition, velocity, inertia_form
|
|
29
29
|
|
|
30
30
|
from scipy.sparse.linalg import factorized
|
|
31
31
|
|
|
32
|
-
import matplotlib.pyplot as plt
|
|
33
|
-
import matplotlib.animation as animation
|
|
34
|
-
|
|
35
32
|
|
|
36
|
-
@integrand
|
|
33
|
+
@fem.integrand
|
|
37
34
|
def vel_mass_form(
|
|
38
|
-
s: Sample,
|
|
39
|
-
u: Field,
|
|
40
|
-
v: Field,
|
|
35
|
+
s: fem.Sample,
|
|
36
|
+
u: fem.Field,
|
|
37
|
+
v: fem.Field,
|
|
41
38
|
):
|
|
42
39
|
return wp.dot(v(s), u(s))
|
|
43
40
|
|
|
44
41
|
|
|
45
|
-
@integrand
|
|
42
|
+
@fem.integrand
|
|
46
43
|
def half_diffusion_form(
|
|
47
|
-
s: Sample,
|
|
48
|
-
domain: Domain,
|
|
49
|
-
psi: Field,
|
|
50
|
-
u: Field,
|
|
44
|
+
s: fem.Sample,
|
|
45
|
+
domain: fem.Domain,
|
|
46
|
+
psi: fem.Field,
|
|
47
|
+
u: fem.Field,
|
|
51
48
|
):
|
|
52
|
-
return jump(psi, s) * wp.dot(average(u, s), normal(domain, s))
|
|
49
|
+
return fem.jump(psi, s) * wp.dot(fem.average(u, s), fem.normal(domain, s))
|
|
53
50
|
|
|
54
51
|
|
|
55
|
-
@integrand
|
|
56
|
-
def upwind_transport_form(s: Sample, domain: Domain, phi: Field, psi: Field, ang_vel: float):
|
|
52
|
+
@fem.integrand
|
|
53
|
+
def upwind_transport_form(s: fem.Sample, domain: fem.Domain, phi: fem.Field, psi: fem.Field, ang_vel: float):
|
|
57
54
|
pos = domain(s)
|
|
58
55
|
|
|
59
56
|
vel = velocity(pos, ang_vel)
|
|
60
57
|
|
|
61
|
-
vel_n = wp.dot(vel, normal(domain, s))
|
|
58
|
+
vel_n = wp.dot(vel, fem.normal(domain, s))
|
|
62
59
|
|
|
63
|
-
return jump(psi, s) * (average(phi, s) * vel_n + 0.5 * jump(phi, s) * wp.abs(vel_n))
|
|
60
|
+
return fem.jump(psi, s) * (fem.average(phi, s) * vel_n + 0.5 * fem.jump(phi, s) * wp.abs(vel_n))
|
|
64
61
|
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
wp.init()
|
|
68
|
-
wp.set_module_options({"enable_backward": False})
|
|
69
|
-
|
|
63
|
+
class Example:
|
|
70
64
|
parser = argparse.ArgumentParser()
|
|
71
65
|
parser.add_argument("--resolution", type=int, default=50)
|
|
72
|
-
parser.add_argument("--
|
|
66
|
+
parser.add_argument("--num_frames", type=int, default=250)
|
|
73
67
|
parser.add_argument("--viscosity", type=float, default=0.001)
|
|
74
68
|
parser.add_argument("--ang_vel", type=float, default=1.0)
|
|
75
|
-
parser.add_argument("--
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
69
|
+
parser.add_argument("--mesh", choices=("grid", "tri", "quad"), default="grid", help="Mesh type")
|
|
70
|
+
|
|
71
|
+
def __init__(self, stage=None, quiet=False, args=None, **kwargs):
|
|
72
|
+
if args is None:
|
|
73
|
+
# Read args from kwargs, add default arg values from parser
|
|
74
|
+
args = argparse.Namespace(**kwargs)
|
|
75
|
+
args = Example.parser.parse_args(args=[], namespace=args)
|
|
76
|
+
self._args = args
|
|
77
|
+
self._quiet = quiet
|
|
78
|
+
|
|
79
|
+
res = args.resolution
|
|
80
|
+
self.sim_dt = 1.0 / (args.ang_vel * res)
|
|
81
|
+
self.current_frame = 0
|
|
82
|
+
|
|
83
|
+
if args.mesh == "tri":
|
|
84
|
+
positions, tri_vidx = gen_trimesh(res=wp.vec2i(args.resolution))
|
|
85
|
+
geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
|
|
86
|
+
elif args.mesh == "quad":
|
|
87
|
+
positions, quad_vidx = gen_quadmesh(res=wp.vec2i(args.resolution))
|
|
88
|
+
geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
|
|
89
|
+
else:
|
|
90
|
+
geo = fem.Grid2D(res=wp.vec2i(args.resolution))
|
|
91
|
+
|
|
92
|
+
domain = fem.Cells(geometry=geo)
|
|
93
|
+
sides = fem.Sides(geo)
|
|
94
|
+
scalar_space = fem.make_polynomial_space(geo, degree=0)
|
|
95
|
+
|
|
96
|
+
# Inertia matrix
|
|
97
|
+
self._test = fem.make_test(space=scalar_space, domain=domain)
|
|
98
|
+
trial = fem.make_trial(space=scalar_space, domain=domain)
|
|
99
|
+
matrix_inertia = fem.integrate(
|
|
100
|
+
inertia_form,
|
|
101
|
+
fields={"phi": trial, "psi": self._test},
|
|
102
|
+
values={"dt": self.sim_dt},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Upwind transport term
|
|
106
|
+
side_test = fem.make_test(space=scalar_space, domain=sides)
|
|
107
|
+
side_trial = fem.make_trial(space=scalar_space, domain=sides)
|
|
108
|
+
matrix_transport = fem.integrate(
|
|
109
|
+
upwind_transport_form,
|
|
110
|
+
fields={"phi": side_trial, "psi": side_test},
|
|
111
|
+
values={"ang_vel": args.ang_vel},
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Diffusion bilinear form
|
|
115
|
+
# Since we have piecewise constant element, we cannot use the classical diffusion form
|
|
116
|
+
# Instead we assemble the matrix B M^-1 B^T, with B associated to the form psi div(u)
|
|
117
|
+
# and the diagonal matrix M to the velocity mass form u.v
|
|
118
|
+
|
|
119
|
+
velocity_space = fem.make_polynomial_space(geo, degree=0, dtype=wp.vec2)
|
|
120
|
+
side_trial_vel = fem.make_trial(space=velocity_space, domain=sides)
|
|
121
|
+
matrix_half_diffusion = fem.integrate(
|
|
122
|
+
half_diffusion_form,
|
|
123
|
+
fields={"psi": side_test, "u": side_trial_vel},
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Diagonal velocity mass matrix
|
|
127
|
+
test_vel = fem.make_test(space=velocity_space, domain=domain)
|
|
128
|
+
trial_vel = fem.make_trial(space=velocity_space, domain=domain)
|
|
129
|
+
inv_vel_mass_matrix = fem.integrate(
|
|
130
|
+
vel_mass_form, domain=domain, fields={"u": trial_vel, "v": test_vel}, nodal=True
|
|
131
|
+
)
|
|
132
|
+
invert_diagonal_bsr_mass_matrix(inv_vel_mass_matrix)
|
|
133
|
+
|
|
134
|
+
# Assemble system matrix
|
|
135
|
+
|
|
136
|
+
matrix = matrix_inertia
|
|
137
|
+
# matrix += matrix_transport
|
|
138
|
+
bsr_axpy(x=matrix_transport, y=matrix)
|
|
139
|
+
# matrix += nu * B M^-1 B^T
|
|
140
|
+
bsr_mm(
|
|
141
|
+
x=bsr_mm(matrix_half_diffusion, inv_vel_mass_matrix),
|
|
142
|
+
y=bsr_transposed(matrix_half_diffusion),
|
|
143
|
+
z=matrix,
|
|
144
|
+
alpha=args.viscosity,
|
|
145
|
+
beta=1.0,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Compute LU factorization of system matrix
|
|
149
|
+
self._solve_lu = factorized(bsr_to_scipy(matrix))
|
|
150
|
+
|
|
151
|
+
# Initial condition
|
|
152
|
+
self._phi_field = scalar_space.make_field()
|
|
153
|
+
fem.interpolate(initial_condition, dest=self._phi_field)
|
|
154
|
+
|
|
155
|
+
self.renderer = Plot(stage)
|
|
156
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
157
|
+
|
|
158
|
+
def update(self):
|
|
159
|
+
self.current_frame += 1
|
|
160
|
+
|
|
161
|
+
rhs = fem.integrate(
|
|
155
162
|
inertia_form,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
values={"dt": dt},
|
|
163
|
+
fields={"phi": self._phi_field, "psi": self._test},
|
|
164
|
+
values={"dt": self.sim_dt},
|
|
159
165
|
)
|
|
160
166
|
|
|
161
|
-
|
|
162
|
-
|
|
167
|
+
self._phi_field.dof_values = self._solve_lu(rhs.numpy())
|
|
168
|
+
|
|
169
|
+
def render(self):
|
|
170
|
+
self.renderer.begin_frame(time = self.current_frame * self.sim_dt)
|
|
171
|
+
self.renderer.add_surface("phi", self._phi_field)
|
|
172
|
+
self.renderer.end_frame()
|
|
173
|
+
|
|
163
174
|
|
|
164
|
-
|
|
165
|
-
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
wp.init()
|
|
177
|
+
wp.set_module_options({"enable_backward": False})
|
|
166
178
|
|
|
167
|
-
|
|
168
|
-
ax = colormesh.axes
|
|
179
|
+
args = Example.parser.parse_args()
|
|
169
180
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
181
|
+
example = Example(args=args)
|
|
182
|
+
for k in range(args.num_frames):
|
|
183
|
+
print(f"Frame {k}:")
|
|
184
|
+
example.update()
|
|
185
|
+
example.render()
|
|
174
186
|
|
|
175
|
-
|
|
176
|
-
ax.figure,
|
|
177
|
-
animate,
|
|
178
|
-
interval=30,
|
|
179
|
-
blit=False,
|
|
180
|
-
frames=len(results),
|
|
181
|
-
)
|
|
182
|
-
plt.show()
|
|
187
|
+
example.renderer.plot()
|