ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Taichi 精选示例实战指南:从物理仿真到稀疏数据结构与 Marching Cubes

Taichi 精选示例实战指南:从物理仿真到稀疏数据结构与 Marching Cubes Taichi 精选示例实战指南从物理仿真到稀疏数据结构与 Marching Cubes【免费下载链接】taichiProductive, portable, and performant GPU programming in Python.项目地址: https://gitcode.com/GitHub_Trending/ta/taichi导读misc/examples.md是 Taichi 仓库维护的一张旗舰示例速览页集中收录了最能体现 Taichi 核心能力的 8 个代表性程序覆盖可微物理仿真MPM 弹性体、FEM 有限元、Position Based Fluids 流体、元胞自动机Game of Life、弹簧质点布料、Marching Cubes 网格提取与稀疏数据结构Sparse Grids等方向。本文以这些官方示例为主线结合python/taichi/examples/下的真实源码逐一拆解每个示例的物理模型、Taichi 语法要点与运行方式帮助读者在跑通演示的同时掌握将 Taichi 应用于数值计算与交互式 GPU 编程的方法。读完本文你将能够使用ti example一键运行/导出/打印这些官方示例理解自动微分ti.ad.Tape、稀疏 SNode 布局、统一粒子网格PIC/APIC与 Marching Cubes 查表等关键技术的代码级实现并在此基础上改写出自己的仿真程序。一、示例总览与运行方式1.1 八个旗舰示例一览misc/examples.md精选的 8 个示例及对应源码路径如下均在 python/taichi/examples 目录下示例源码路径技术主题MPM 拉格朗日力仿真simulation/mpm_lagrangian_forces.py可微 MPM 能量最小化Neo-HookeanSparse Gridsfeatures/sparse/taichi_sparse.py稀疏指针 SNode 与活动块查询2D Position Based Fluidssimulation/pbf2d.pyPBF 流体约束求解Conways Game of Lifesimulation/game_of_life.py元胞自动机 GUI 交互FEM 弹性体128 单元simulation/fem128.py有限元 ti.ad.Tape自动微分3D 布料弹簧质点ggui_examples/mass_spring_3d_ggui.py弹簧-阻尼布料 GGUI 3D 渲染Marching Cubesalgorithm/mciso_advanced.py2D/3D 等值面提取 PLY 导出3D MPMsimulation/mpm3d.py三维雪花/弹性体 MPM说明misc/examples.md中引用的simulation/mass_spring_3d.py在当前仓库中已迁移为 GGUI 版本 ggui_examples/mass_spring_3d_ggui.py本文以仓库现有源码为准。1.2 使用ti example命令运行这些示例统一通过ti example子命令管理。在 python/taichi/_main.py 中可以看到其完整实现命令首先扫描examples目录下所有*.py文件并建立示例名 - 目录映射_get_available_examplespython/taichi/_main.py随后支持交互式选择或直接指定示例名运行。# 列出全部可用示例并以交互方式选择运行 ti example # 直接运行指定示例示例名取源码文件名去掉 .py ti example mpm88 ti example pbf2d ti example taichi_sparse # 打印示例源码而不运行 ti example game_of_life -p # 带行号、语法高亮的富文本打印 ti example fem128 -P # 将示例源码保存到当前目录 ti example mciso_advanced -s其中-p/-P/-s三个参数分别对应 python/taichi/_main.py 中定义的--print、--pretty-print与--save。运行时会通过runpy.run_path(target, run_name__main__)以模块方式执行目标文件python/taichi/_main.py因此示例内的if __name__ __main__: main()入口会被正常触发。ti example之外仓库还提供了交互式图库ti gallerypython/taichi/_main.py可以用鼠标在图形界面中挑选并运行示例。也可以直接以 Python 脚本方式运行源码python python/taichi/examples/simulation/mpm3d.py python python/taichi/examples/features/sparse/taichi_sparse.py1.3 运行前的环境说明示例中ti.init(archti.gpu)会自动选择可用的 GPU 后端CUDA/Vulkan/Metal 等无 GPU 时可手动改为ti.init(archti.cpu)运行如 simulation/game_of_life.py 默认不指定 arch。GUI 示例依赖 Taichi 内置的ti.GUICPU 窗口或ti.ui.WindowGGUI3D 渲染需要图形环境。硬件相关示例如ti.cuda需要对应驱动与后端支持例如 features/sparse/taichi_sparse.py 明确指定archti.cuda。二、可微 MPM拉格朗日力与能量自动微分2.1 示例定位与物理模型simulation/mpm_lagrangian_forces.py 演示了 Taichi 最独特的组合能力MPMMaterial Point Method框架 自动微分计算内力。与传统的先求应力、再插值到网格的做法不同该示例直接把总势能Neo-Hookean 超弹性能量定义为粒子位置的函数通过ti.ad.Tape(total_energy)反向传播得到x.grad即内力F -∂E/∂x再把力项注入粒子到网格P2G的散射过程。核心物理参数见 simulation/mpm_lagrangian_forces.pydim 2 quality 1 # 增大该整数可提升分辨率/质量 n_particle_x 100 * quality n_particle_y 8 * quality n_particles n_particle_x * n_particle_y n_elements (n_particle_x - 1) * (n_particle_y - 1) * 2 # 三角形单元数 n_grid 64 * quality dx 1 / n_grid dt 1e-4 / quality E 25000 # 杨氏模量 p_mass 1 p_vol 1 mu 1 # Lamé 第一参数剪切模量 la 1 # Lamé 第二参数quality是一个全局质量开关将其从 1 调大到 2、4粒子数、网格数与时间步都会按比例细化直接获得更精细的仿真结果。2.2 能量计算与自动微分示例用needs_gradTrue标记位置场与能量场simulation/mpm_lagrangian_forces.pyx ti.Vector.field(dim, dtypefloat, shapen_particles, needs_gradTrue) ... total_energy ti.field(dtypefloat, shape(), needs_gradTrue)compute_total_energy内核遍历三角形单元计算变形梯度F currentT restT[i].inverse()再按 Neo-Hookean 公式累加单元能量simulation/mpm_lagrangian_forces.pyI1 (F F.transpose()).trace() J F.determinant() element_energy 0.5 * mu * (I1 - 2) - mu * ti.log(J) 0.5 * la * ti.log(J) ** 2 total_energy[None] E * element_energy * dx * dx主循环中每一帧先用ti.ad.Tape(total_energy)包裹前向能量计算自动完成反向传播simulation/mpm_lagrangian_forces.pywith ti.ad.Tape(total_energy): compute_total_energy() p2g() # 此时 x.grad 已携带内力被 p2g 用于速度散射在p2g内核中可以看到力项- dt * x.grad[p]直接参与 APIC 风格的 affine 散射simulation/mpm_lagrangian_forces.pygrid_v[base I] weight * (p_mass * v[p] - dt * x.grad[p] affine dpos) grid_m[base I] weight * p_mass随后grid_op完成网格速度归一化、重力施加与碰撞中心圆 边界盒见 simulation/mpm_lagrangian_forces.pyg2p用双三次样条权重回插速度与仿射矩阵Csimulation/mpm_lagrangian_forces.py形成完整的 MPM 时间步。2.3 渲染与交互渲染部分展示了ti.GUI的矢量绘制能力simulation/mpm_lagrangian_forces.pygui.circle绘制中央障碍圆gui.lines用三角形网格索引vertices绘制线框gui.circles绘制粒子gui.line绘制地面。粒子位置通过x.to_numpy()取回 CPU 端网格边用np.roll技巧构造展示了 Taichi field 与 NumPy 数组的无缝互转。三、三维 MPM雪花/弹性体标准实现simulation/mpm3d.py 是更广为人知的 MPM 变体——Taichi 雪花MPM88/MPM3D 系列之一采用经典 MPM 算法不依赖自动微分可作为修改和扩展的基线。文件头部通过注释给出了 2D/3D 多组分辨率与时间步配置simulation/mpm3d.py# dim, n_grid, steps, dt 2, 128, 20, 2e-4 # dim, n_grid, steps, dt 2, 256, 32, 1e-4 dim, n_grid, steps, dt 3, 32, 25, 4e-4 # dim, n_grid, steps, dt 3, 64, 25, 2e-4 # dim, n_grid, steps, dt 3, 128, 25, 8e-5单步substep内核按P2G 散射 - 网格更新/碰撞 - G2P 回插三阶段组织simulation/mpm3d.pyP2G按stress -dt * 4 * E * p_vol * (F_J[p] - 1) / dx**2计算应力并构造 affine 矩阵用ti.static(ti.grouped(ti.ndrange(*neighbour)))静态展开 3×3×3 邻域网格阶段F_grid_v[I] / F_grid_m[I]归一化速度施加重力并用ti.select(cond, 0, F_grid_v[I])处理边界碰撞G2P回插速度与仿射矩阵new_C 4 * weight * g_v.outer_product(dpos) / dx**2并更新形变梯度雅可比F_J[p] * 1 dt * new_C.trace()。ti.loop_config(block_dimn_grid)用于针对该网格规模设置 CUDA block 维度是调优 GPU 内核吞吐量时可参考的实用 API。该示例默认将结果导出为 PLY文件顶部的export_file变量设为/tmp/mpm3d.ply即可写盘可与 features/io/export_ply.py 中的 PLY 导出工具链配合使用。四、Sparse Grids稀疏指针 SNode 实战features/sparse/taichi_sparse.py 是理解 Taichi **稀疏数据结构SNode**的必读示例它用旋转的 Taichi Logo 逐帧激活一个 512×512 的稀疏网格并可视化活动块active block的层级结构。4.1 三层 pointer dense 布局核心布局构造见 features/sparse/taichi_sparse.pyblock1 ti.root.pointer(ti.ij, n // 64) # 第一层指针64×64 个块 block2 block1.pointer(ti.ij, 4) # 第二层指针每块再细分 4×4 block3 block2.pointer(ti.ij, 4) # 第三层指针 block3.dense(ti.ij, 4).place(x) # 最内层 dense 4×4实际存放数据这样x实际被组织成 3 层指针 1 层稠密的结构n 512则块大小为64 × 4 × 4 × 4 512形成经典的多分辨率稀疏金字塔。pointer节点按需分配、未激活时零内存占用这是稀疏网格如体素场景节省显存的关键机制。4.2 激活、旋转与活动块可视化activate内核逐帧读取旋转矩阵ti.math.rotation2d(ti.sin(t))变换坐标命中 Logo 像素的位置置 1features/sparse/taichi_sparse.py其中taichi_logo来自 python/taichi/examples/patterns.py是一个返回布尔结果的 SDF 风格符号距离函数。paint内核则演示了三个稀疏 API 的组合features/sparse/taichi_sparse.pyti.rescale_index(x, block, [i, j])把数据坐标缩放到指定块层的索引ti.is_active(block, idx)查询某层块是否已激活三层结果叠加后映射为灰度img[scatter(i), scatter(j)] 1 - t / 4输出可视化图。主循环中block1.deactivate_all()每帧清空全部活动块再重新激活features/sparse/taichi_sparse.py直观展示活动块随 Logo 旋转动态分配/回收的过程。这种按需激活 层级查询的模式正是 python/taichi/examples/features/sparse 目录下taichi_dynamic.py动态长度数组、taichi_bitmasked.py位掩码稀疏等进阶示例的共同基础。五、Position Based Fluids2D 流体约束求解simulation/pbf2d.py 实现了 Macklin Müller 2013 年的 PBFPosition Based Fluids算法文件头标注了论文出处与原作者 Ye Kuang用纯位置投影的方式求解不可压缩约束无需显式压力项。5.1 领域构建与邻居查找示例为 60×20 的粒子网格构建了统一空间哈希网格simulation/pbf2d.pyti.root.dense(ti.i, num_particles).place(old_positions, positions, velocities) grid_snode ti.root.dense(ti.ij, grid_size) grid_snode.place(grid_num_particles) grid_snode.dense(ti.k, max_num_particles_per_cell).place(grid2particles)其中grid2particles是一个dense(ti.k, 100)的每格粒子索引表配合ti.atomic_add(grid_num_particles[cell], 1)simulation/pbf2d.py实现并行无冲突的格子填充。prologue内核随后遍历 3×3 邻域格子把距离小于neighbor_radius的粒子写入particle_neighbors并统计每粒子邻居数simulation/pbf2d.py。5.2 约束求解三阶段substep内核按 PBF 论文公式逐步求解simulation/pbf2d.py用 Spiky 核梯度与 Poly6 核计算密度约束density_constraint (mass * density_constraint / rho0) - 1.0并累加sum_gradient_sqr得到拉格朗日乘子lambdas[p_i] -density_constraint / (sum_gradient_sqr lambda_epsilon)对应论文 Eq. 8-11用compute_scorr论文 Eq. 13 的人工压力项代码中以x*x*x*x实现 4 次幂修正位置增量pos_delta_i (lambda_i lambda_j scorr_ij) * spiky_gradient(pos_ji, h_)Eq. 12, 14应用位置增量并除以rho0。epilogue内核把新位置约束回边界并反推速度velocities[i] (positions[i] - old_positions[i]) / time_deltasimulation/pbf2d.py。值得注意的细节confine_position_to_boundary在钳制位置时混入epsilon * ti.random()随机抖动避免粒子粘连simulation/pbf2d.py。5.3 交互与性能统计主循环中右侧挡板通过move_board内核做正弦往复运动b[0] -ti.sin(...) * vel_strength * time_delta见 simulation/pbf2d.py用于演示流体与动态边界的交互。示例还提供print_statssimulation/pbf2d.py每 20 帧打印一次每格粒子数 / 每粒子邻居数的平均值与最大值可作为验证空间哈希与邻居查找性能的观测指标。六、FEM 弹性体128 单元有限元 自动微分simulation/fem128.py 把有限元FEM与自动微分结合不手写刚度矩阵而是直接对总势能U求梯度得到节点力。6.1 网格与材料参数代码顶部定义材料与几何参数simulation/fem128.pyN 12 dt 5e-5 dx 1 / N rho 4e1 NF 2 * N**2 # 三角形面片数 NV (N 1) ** 2 # 顶点数 E, nu 4e4, 0.2 # 杨氏模量、泊松比 mu, lam E / 2 / (1 nu), E * nu / (1 nu) / (1 - 2 * nu) # Lamé 参数 ball_pos, ball_radius ti.Vector([0.5, 0.0]), 0.31 damping 14.5init_mesh内核把 12×12 网格切成三角形f2v记录每面三个顶点索引init_pos计算每面的初始形状矩阵B其逆矩阵用于后续变形梯度计算见 simulation/fem128.py 与 simulation/fem128.py。6.2 势能计算与时间积分update_U内核先对每面计算变形梯度F[i] D_i B[i]再累加 Neo-Hookean 势能simulation/fem128.pylog_J_i ti.log(F_i.determinant()) phi_i mu / 2 * ((F_i.transpose() F_i).trace() - 2) phi_i - mu * log_J_i phi_i lam / 2 * log_J_i**2 phi[i] phi_i U[None] V[i] * phi_i时间积分在advance内核中完成simulation/fem128.py加速度来自-pos.grad[i] / (rho * dx**2)即势能梯度 内力叠加重力与鼠标吸引/排斥力速度乘以ti.exp(-dt * damping)实现阻尼随后处理球体碰撞disp2 ball_radius**2时投影速度与矩形边界。主循环每帧执行 50 次自动微分 积分simulation/fem128.pyfor i in range(50): with ti.ad.Tape(lossU): update_U() advance()交互方式simulation/fem128.pyWASD/方向键控制重力方向鼠标左键吸引、右键排斥R复位。渲染用gui.triangles按势能密度着色paint_phi红-灰渐变直观呈现应力分布。七、3D 布料弹簧质点 GGUI 场景渲染ggui_examples/mass_spring_3d_ggui.py 将 128×128 质点的布料模型接入 Taichi GGUIVulkan 图形界面展示弹簧-阻尼系统与 3D 场景 API 的组合用法。7.1 弹簧布局与力模型示例在每帧初始化时对每个质点周围 4×4含对角线距离 ≤ 2的邻域建立弹簧spring_offsets并可通过bending_springs开关切换到 3×3 邻域的弯曲弹簧模式ggui_examples/mass_spring_3d_ggui.py。核心参数见 ggui_examples/mass_spring_3d_ggui.pyn 128 quad_size 1.0 / n dt 4e-2 / n substeps int(1 / 60 // dt) gravity ti.Vector([0, -9.8, 0]) spring_Y 3e4 # 弹簧刚度 dashpot_damping 1e4 # 阻尼器 drag_damping 1 # 空气阻力 ball_radius 0.3substep内核实现三类力重力、弹簧力-spring_Y * d * (current_dist / original_dist - 1)以当前/原始长度比驱动与阻尼力-v_ij.dot(d) * d * dashpot_damping * quad_size最后对撞到中心球的质点做速度投影ggui_examples/mass_spring_3d_ggui.py。7.2 GGUI 场景搭建渲染层展示了 GGUI 的完整流程ggui_examples/mass_spring_3d_ggui.pywindow ti.ui.Window(Taichi Cloth Simulation on GGUI, (768, 768), vsyncTrue) canvas window.get_canvas() scene window.get_scene() camera ti.ui.Camera() ... camera.position(0.0, 0.0, 3) camera.lookat(0.0, 0.0, 0) scene.set_camera(camera) scene.point_light(pos(0, 1, 2), color(1, 1, 1)) scene.ambient_light((0.5, 0.5, 0.5)) scene.mesh(vertices, indicesindices, per_vertex_colorcolors, two_sidedTrue) scene.particles(ball_center, radiusball_radius * 0.95, color(0.5, 0.42, 0.8)) canvas.scene(scene) window.show()其中indices由initialize_mesh_indices生成每 6 个索引一组的两三角形面片ggui_examples/mass_spring_3d_ggui.pycolors按棋盘格模式给顶点着色。运行 1.5 秒后布料自动复位current_t 1.5触发initialize_mass_points()适合循环展示。该示例与 ggui_examples 目录下的mpm3d_ggui.py、stable_fluid_ggui.py等一起构成了 GGUI 3D 应用的参考集。八、Marching Cubes等值面提取与 PLY 导出algorithm/mciso_advanced.py 用ti.data_oriented类封装了一个可复用的 MCISO 提取器支持 2DMarching Squares与 3DMarching Cubes两种维度并演示pointer稀疏加速。8.1 查表结构与数据布局MCISO类内置两张查找表et22D16 种角点组合与et33D256 种组合对应标准 15 条边编号注释中给出了表来源链接见 algorithm/mciso_advanced.py并通过ti.Vector.field(dim, int, et.shape[:2])from_numpy载入 Taichi 场algorithm/mciso_advanced.py。标量场m与梯度场g的布局支持稠密/稀疏两种模式algorithm/mciso_advanced.pyif self.use_sparse: ti.root.pointer(indices, self.N // self.blk_size).dense(indices, self.blk_size).place(self.m) ti.root.dense(indices, self.N).place(self.g) else: ti.root.dense(indices, self.N).place(self.m) ti.root.dense(indices, self.N).place(self.g)use_sparse blk_size is not None实例化时传入blk_size即可启用稀疏模式——这与第四节 Sparse Grids 的pointer用法一脉相承。8.2 梯度计算与并行 Marchcompute_grad用中心差分计算归一化梯度r[i] self.m[I d] - self.m[I - d]见 algorithm/mciso_advanced.py。核心的march内核逐体素2D 逐像素按位拼接角点状态得到查表索引idx再对每个命中边用线性插值求交p (1 - self.m[i, j]) / (self.m[i 1, j] - self.m[i, j]) R [i p, j]并使用n ti.atomic_add(r_n, 1)algorithm/mciso_advanced.py在并行内核内原子分配输出缓冲槽位最终返回写入的顶点数r_n。8.3 交互、渲染与导出MCISO_Example.main提供实时交互algorithm/mciso_advanced.py鼠标拖动通过touch内核写入高斯混合标量场每次移动重新march2D 模式渲染梯度场灰度图与等值线3D 模式绘制三角面片并按空格键用ti.tools.PLYWriter把网格写入mciso_output.ply。ti.deactivate_all_snodes()稀疏模式下或self.m.fill(0)稠密模式负责每帧重置场数据。三维网格提取如从 SDF/体素场重建表面通常还需要法线、UV 等附加属性可参考 features/io/export_mesh.py 的完整导出链。九、Game of Life100 行元胞自动机与 GUI 交互simulation/game_of_life.py 是入门 Taichi 的最简交互示例约 100 行实现 Conway 生命游戏文件头注释致敬了 Conway1937–2020。9.1 规则实现游戏在 64×64 的alive场上进行simulation/game_of_life.pyn 64 cell_size 8 alive ti.field(int, shape(n, n)) count ti.field(int, shape(n, n))get_count通过 8 个方向累加邻居存活数边界外视为 0calc_rule用ti.static展开规则表B, S [3], [2, 3]重生/存活规则simulation/game_of_life.py。run内核分成两个独立循环先算邻居计数、再更新状态避免就地更新带来的竞争simulation/game_of_life.py。把B, S改成其他组合如[2], [0]注释中已给出即可切换到其他元胞自动机规则。9.2 GUI 交互与图像放大主循环演示了ti.GUI的事件系统simulation/game_of_life.pyfor e in gui.get_events(gui.PRESS, gui.MOTION): if e.key gui.ESCAPE: gui.running False elif e.key gui.SPACE: paused not paused elif e.key r: alive.fill(0) if gui.is_pressed(gui.LMB, gui.RMB): mx, my gui.get_cursor_pos() alive[int(mx * n), int(my * n)] gui.is_pressed(gui.LMB) paused True交互操作包括空格暂停/继续、r清空重来、鼠标左键画存活细胞、右键画死细胞窗口帧率通过gui.fps_limit 15限制。显示时用ti.tools.imresize(alive, img_size)把 64×64 整数场放大到 512×512 再转 uint8 输出simulation/game_of_life.py这是ti.tools图像工具的一个典型用法。十、延伸学习路径以上 8 个示例覆盖了 Taichi 的主要能力象限仓库中还有大量同主题姊妹示例可继续研读更多 MPM/流体simulation/mpm88.py、simulation/mpm128.py、simulation/stable_fluid.py、simulation/eulerfluid2d.py以及带自动微分的 simulation/ad_gravity.py稀疏进阶features/sparse/taichi_dynamic.py、features/sparse/taichi_bitmasked.py、features/sparse/explicit_activation.py自动微分autodiff 目录下的simple_derivative.py、jacobian.py、regression.py、minimization.pyGGUI 3Dggui_examples 目录下的mpm3d_ggui.py、stable_fluid_ggui.py、fractal3d_ggui.py、mass_spring_game_ggui.py渲染rendering 目录下的cornell_box.py、sdf_renderer.py、rasterizer.py、taichi_ngp.py图模式Graphgraph 目录下的mpm88_graph.py、stable_fluid_graph.py展示ti.graph的 AOT 化调用方式IOfeatures/io 目录下的export_videos.py、export_ply.py、export_mesh.py可学习如何把仿真结果导出为视频与网格文件。运行上述任一示例只需ti example 示例名或在 python/taichi/examples 目录中直接阅读源码。建议按照Game of Life入门→ Sparse Grids数据结构→ PBF2D / MPM3D数值仿真→ fem128 / mpm_lagrangian_forces自动微分→ mciso_advanced网格提取→ mass_spring_3d_ggui3D 渲染的顺序逐步深入即可系统掌握 Taichi 从基础语法到高级特性的完整技术栈。【免费下载链接】taichiProductive, portable, and performant GPU programming in Python.项目地址: https://gitcode.com/GitHub_Trending/ta/taichi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表