【GAMES201学习笔记】物质点法入门

2023-10-20 21:50

本文主要是介绍【GAMES201学习笔记】物质点法入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 流体力学中的两种描述

1.1 拉格朗日描述

1.1.1 什么是拉格朗日描述

拉格朗日描述 的观察对象是组成物体的 质点粒子(particle) ,或者说 流体微元

  • 随着物体变化,对应 “粒子” 的位置也会随之变化,跟踪的观察对象是单个 “粒子” 的属性变化;
  • 拉格朗日描述最显著的特征就是观察对象会发生位置或者形状的变换。

1.1.2 常见的使用拉格朗日描述的方法

  • 弹簧质点模型(观察质点的变换)
  • 有限元法(观察有限微元的变换)

1.1.3 拉格朗日描述擅长的地方

  • 拉格朗日描述擅长对独立粒子的操作;
  • 物体的变换操作:这时对粒子施加相应的变换即可;
  • 粒子的质量和动量守恒是简单的;
  • 定义物体的材质:定义单个粒子相关参数。

1.1.4 拉格朗日描述不擅长的地方

由于粒子经过变换之后,对应的位置和形变都是不确定的,因此虽然可以查询之前已经建立了 邻接信息 的粒子之间的关系(当然,在拉格朗日中找邻接粒子本身是一个困难的问题);但查询未确立 邻接信息 的粒子之间的关系(例如任意两个粒子之间的距离),会异常困难。

这导致当有查询 未邻接的两个粒子 之间关系的需求时,会遇到一定的麻烦:例如在使用有限元进行仿真时,如果没有合理处理自相交问题,会发生模型穿透的情况。

弹性方块的 FEM 模拟

FEM_Cube.gif

弹性平面的 FEM 模拟

  • 由于仅做了邻接粒子之间、粒子与球之间的碰撞检测,所以在平面折叠时发生了穿透。

FEM_Plane.gif

不过目前在有限元领域,对于碰撞问题,也已经有了对应的解决方案:

  • [SIGGRAPH 2020] Incremental Potential Contact (IPC)

1.2 欧拉描述

1.2.1 什么是欧拉描述

欧拉描述 的观察对象是物体所在 空间的场网格(Grid) ,或者说 流体元胞(Cell)

  • 网格是在空间中的绝对参照系的微元,随着物体变化,网格的位置和形状不会随之变化,仅物体映射到网格上的信息发生改变;
  • 欧拉描述最显著的特征就是观察对象不会发生位置或者形状的变换。

1.2.2 欧拉描述擅长的地方

  • 拉格朗日描述擅长处理粒子之间的相对关系;
  • 物体性质的变化:质量密度、速度、温度、熵、焓,甚至单位流体中的磁通量;
  • 物体内部的压力压强计算,可以很快的获得能量密度函数;
  • 边界碰撞检测:欧拉描述可以很快的获得任意粒子之间的相对关系信息,或者说在欧拉视角下物体自然而然地在进行着碰撞检测。

1.2.3 欧拉描述不擅长的地方

  • 物体的变换:显然,拉格朗日描述擅长的地方就是欧拉描述不擅长的地方,在物体发生变换的过程中,需要更新网格和相邻网格的信息,这个过程是较为繁琐的。

2. Particle-In-Cell methods(PIC)

Note

  • 在混合拉格朗日 - 欧拉方法中,“粒子”是一等公民,“网格”是用来计算场信息的中间量。

2.1 粒子信息映射到网格(P2G)

2.1.1 思路

将粒子信息映射到网格上,或者说从一组粒子重建整个场的信息,这里采用了一个 SPH 中处理类似问题的方法:

  • 使用一个径向对称的 核函数 (有时称为 基函数 ),来确定一个粒子对周边空间的 “影响(贡献)”,即一种加权计算 ;
  • 其中粒子的影响是局部化的,核函数通常选择 有限支撑 ,即存在一个最大支撑距离;
  • 核函数是归一化的: ∮ R N ^ ( r ) d r = 1 \oint_{R} \hat{N}(\bold{r})d\bold{r} = 1 RN^(r)dr=1 ,其中 R R R 是整个支撑集。

B 样条核函数

screenShot.png

在二维空间下,仅考虑粒子周围的九个网格节点。

screenShot.png

2.1.2 代码实现

mpm88.py Line 30,42 (除去了 APIC 的部分):

for p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - base# Quadratic B-splinew = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])weight = w[i].x * w[j].ygrid_v[base + offset] += weight * (p_mass * v[p])grid_m[base + offset] += weight * p_mass

Note

  • 粒子在中间网格里;
  • base :粒子所在周边网格的网格点 p [ 0 , 0 ] \bold{p}_{[0,0]} p[0,0] ,坐标 (0.5 * dx, 0.5 * dx)
  • fx :粒子距离网格点 p [ 0 , 0 ] \bold{p}_{[0,0]} p[0,0] 的距离;
     
  • 距离中间的网格点: ω = 3 4 − ∣ ( x p − x b a s e ) − 1 ∣ 2 \omega = \frac{3}{4} - \vert (\bold{x}_p - \bold{x}_{base}) - 1 \vert^2 ω=43(xpxbase)12
     
  • 距离靠左下的网格点: ω = 1 2 ( 3 2 − ∣ x p − x b a s e ∣ ) 2 \omega = \frac{1}{2}(\frac{3}{2} - \vert \bold{x}_p - \bold{x}_{base} \vert)^2 ω=21(23xpxbase)2
     
  • 距离靠右上的网格点: ω = 1 2 ( 2 − ( 3 2 − ∣ x p − x b a s e ∣ ) ) 2 = 1 2 ( ∣ x p − x b a s e ∣ − 1 2 ) 2 \omega = \frac{1}{2}(2 - (\frac{3}{2} - \vert \bold{x}_p - \bold{x}_{base} \vert))^2 = \frac{1}{2}(\vert \bold{x}_p - \bold{x}_{base} \vert - \frac{1}{2})^2 ω=21(2(23xpxbase))2=21(xpxbase21)2

screenShot.png

mpm88.py Line 43,46:

# 对速度做一个网格质量的加权平均
for i, j in grid_m:if grid_m[i, j] > 0:grid_v[i, j] /= grid_m[i, j]grid_v[i, j].y -= dt * gravity

2.2 网格信息叠加到粒子(G2P)

2.1.1 思路

在计算完网格上各种场的对应信息之后,将周围网格的信息叠加到原粒子上。

2.2.2 代码实现

mpm88.py Line 55,68 (除去了 APIC 的部分):

for p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - base# Quadratic B-spline w = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]new_v = ti.Vector.zero(float, 2)for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])weight = w[i].x * w[j].ynew_v += weight * g_vv[p] = new_vx[p] += dt * v[p]

2.3 PIC 的局限性

主要是在 G2P 的过程中,粒子信息是由网格信息叠加而成的,存在大量的信息缺失,直观来说就是出现了能量损耗,主要在旋转和切变的过程(主要是角动量损耗及其严重)。

  • 以速度场为例,粒子拥有 2 个自由度,而一个 3×3 的网格点有 18 个自由度:

screenShot.png

3. Affine Particle-In-Cell(APIC)

3.1 APIC 简介

screenShot.png

通过 2.3 可知,PIC 在场信息到粒子信息的过程中存在信息缺失的情况,这时不妨在这个过程中存储更多的场的信息:

符 号含 义
v 0 \bold{v}_0 v0 v 1 \bold{v}_1 v1均匀常量速度场,描述粒子原本的 2 个自由度的速度信息,不会随着 x p \bold{x}_p xp 位置的变化而变化。
C 00 \bold{C}_{00} C00随着粒子在 x 分量的变化,在 x 分量上线性变化的速度场,场的分量 C[0] 随着 x[p][0] 变化的情况。
C 10 \bold{C}_{10} C10随着粒子在 x 分量的变化,在 y 方向上线性变化的速度场,场的分量 C[1] 随着 x[p][0] 变化的情况。
C 01 \bold{C}_{01} C01随着粒子在 y 分量的变化,在 x 方向上线性变化的速度场,场的分量 C[0] 随着 x[p][1] 变化的情况。
C 11 \bold{C}_{11} C11随着粒子在 y 分量的变化,在 y 方向上线性变化的速度场,场的分量 C[1] 随着 x[p][1] 变化的情况。

3.2 APIC 的角动量是守恒的

数学证明见:

  • Tech report: the affine Particle-in-Cell method <5.3.1> <5.3.2>

3.3 代码实现

3.3.1 P2G

mpm88.py Line 30,42(除去压力计算部分):

x = ti.Vector.field(2, float, n_particles)
v = ti.Vector.field(2, float, n_particles)
C = ti.Matrix.field(2, 2, float, n_particles)for p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - base# Quadratic B-splinew = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]affine = C[p]for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])# 网格点位置和粒子位置的偏差值dpos = (offset - fx) * dxweight = w[i].x * w[j].ygrid_v[base + offset] += weight * (p_mass * v[p] + affine @ dpos)grid_m[base + offset] += weight * p_mass

g v = [ g v . x g v . y ] = [ C 00 C 01 C 10 C 11 ] [ d p o s . x d p o s . y ] = [ C 00 ⋅ d p o s . x + C 01 ⋅ d p o s . y C 10 ⋅ d p o s . x + C 11 ⋅ d p o s . y ] \begin{aligned} \bold{g}_v &= \begin{bmatrix} \bold{g}_v.x \\ \bold{g}_v.y \end{bmatrix} \\[3ex] &= \begin{bmatrix} \bold{C}_{00} & \bold{C}_{01} \\ \bold{C}_{10} & \bold{C}_{11} \end{bmatrix} \begin{bmatrix} \bold{d}_{pos}.x \\ \bold{d}_{pos}.y \end{bmatrix} \\[3ex] &= \begin{bmatrix} \bold{C}_{00} \cdot \bold{d}_{pos}.x + \bold{C}_{01} \cdot \bold{d}_{pos}.y\\ \bold{C}_{10} \cdot \bold{d}_{pos}.x + \bold{C}_{11} \cdot \bold{d}_{pos}.y \end{bmatrix} \end{aligned} gv=[gv.xgv.y]=[C00C10C01C11][dpos.xdpos.y]=[C00dpos.x+C01dpos.yC10dpos.x+C11dpos.y]

Note

  • 其中网格点速度 g_v 、粒子位移的差分值 dpos ,与速度场 C 之间的关系,见 3.1 中的表格。

3.3.2 G2P

mpm88.py Line 30,42(除去压力计算部分):

for p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - basew = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]new_v = ti.Vector.zero(float, 2)new_C = ti.Matrix.zero(float, 2, 2)for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])# 网格点位置和粒子位置的偏差值dpos = (offset - fx) * dxweight = w[i].x * w[j].y# 网格点的速度g_v = grid_v[base + offset]new_v += weight * g_vnew_C += 4 * weight * g_v.outer_product(dpos) / dx**2v[p] = new_vx[p] += dt * v[p]C[p] = new_C

C n e w = [ C 00 C 01 C 10 C 11 ] = 4 w Δ x 2 g v ⊗ d p o s = 4 w Δ x 2 [ g v . x g v . y ] [ d p o s . x d p o s . y ] = 4 w Δ x 2 [ g v . x ⋅ d p o s . x g v . x ⋅ d p o s . y g v . y ⋅ d p o s . x g v . y ⋅ d p o s . y ] \begin{aligned} \bold{C}_{new} &= \begin{bmatrix} \bold{C}_{00} & \bold{C}_{01} \\ \bold{C}_{10} & \bold{C}_{11} \end{bmatrix} \\[3ex] &= \cfrac{4w}{{\Delta x}^2} \space \bold{g}_v \otimes \bold{d}_{pos} \\[3ex] &= \cfrac{4w}{{\Delta x}^2} \begin{bmatrix} \bold{g}_v.x \\ \bold{g}_v.y \end{bmatrix} \begin{bmatrix} \bold{d}_{pos}.x & \bold{d}_{pos}.y \end{bmatrix} \\[3ex] &= \cfrac{4w}{{\Delta x}^2} \begin{bmatrix} \bold{g}_v.x \cdot \bold{d}_{pos}.x & \bold{g}_v.x \cdot \bold{d}_{pos}.y \\ \bold{g}_v.y \cdot \bold{d}_{pos}.x & \bold{g}_v.y \cdot \bold{d}_{pos}.y \end{bmatrix} \end{aligned} Cnew=[C00C10C01C11]=Δx24w gvdpos=Δx24w[gv.xgv.y][dpos.xdpos.y]=Δx24w[gv.xdpos.xgv.ydpos.xgv.xdpos.ygv.ydpos.y]

Note

  • 其中网格点速度 g_v 、粒子位移的差分值 dpos ,与速度场 C 之间的关系,见 3.1 中的表格。

3.4 如果需要更精确的解

APIC 可以类比于泰勒一级展开,如果有追求更高精度的需要(二级展开等),则可以使用 ployPIC

  • [SIGGRAPH Asia 2017] A polynomial particle-in-cell method

4. Material Point Method(MPM)

4.1 物质点法简介

在解决了欧拉-拉格朗日之间的信息传递问题之后(APIC),就需要真正开始进行模拟,这时需要额外增加一些信息(形变梯度 F \bold{F} F ,体积应变比 J \bold{J} J ,杨氏模量 E E E 等)

最早的一篇关于 MPM 论文:

  • [SIGGRAPH 2013] A material point method for snow simulation

距 2018 年,MPM 的相关论文:

screenShot.png

4.2 MLS-MPM

screenShot.png

P2G

  • 使用(仿射 Affine)速度更新粒子;
  • 将质量和动量分散到附近的 3×3×3 个节点。

对于每个网格点

  • 用动量除以质量得到速度;
  • 应用重力和边界条件

G2P

  • 从 3×3×3 个节点收集 速度/仿射速度(Affine)。

4.3 代码实现

4.3.1 相关参数

mpm88.py Line 2, 23:

import taichi as ti
ti.init(arch=ti.gpu)n_particles = 8192
n_grid = 128
dx = 1 / n_grid
dt = 2e-4p_rho = 1
p_vol = (dx * 0.5)**2
p_mass = p_vol * p_rho
gravity = 9.8
bound = 3
E = 400x = ti.Vector.field(2, float, n_particles)
v = ti.Vector.field(2, float, n_particles)
C = ti.Matrix.field(2, 2, float, n_particles)
# 体积比(当前体积/初始体积):
# J < 1 :粒子压缩
# J > 1 :粒子膨胀
J = ti.field(float, n_particles)grid_v = ti.Vector.field(2, float, (n_grid, n_grid))
grid_m = ti.field(float, (n_grid, n_grid))

4.3.2 P2G

mpm88.py Line 30, 42:

@ti.kernel
def substep():# init grid...... # P2Gfor p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - basew = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]stress = -dt * 4 * E * p_vol * (J[p] - 1) / dx**2# 动量的仿射信息affine = ti.Matrix([[stress, 0], [0, stress]]) + p_mass * C[p]for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])dpos = (offset - fx) * dxweight = w[i].x * w[j].ygrid_v[base + offset] += weight * (p_mass * v[p] + affine @ dpos)grid_m[base + offset] += weight * p_mass

MPM 中,添加了一项 stress ,表示粒子受到压缩之后推开周围粒子的力(实际上是在网格层面操作):

( m v ) s t r e s s = − 4 Δ x 2 Δ t E p v o l ( J p − 1 ) (mv)_{stress} = - \cfrac{4}{\Delta x^2} \Delta t E \bold{p}_{vol}(J_\bold{p} - 1) (mv)stress=Δx24ΔtEpvol(Jp1)

4.3.3 边界条件

mpm88.py Line 43, 54:

    for i, j in grid_m:if grid_m[i, j] > 0:grid_v[i, j] /= grid_m[i, j]grid_v[i, j].y -= dt * gravityif i < bound and grid_v[i, j].x < 0:grid_v[i, j].x = 0if i > n_grid - bound and grid_v[i, j].x > 0:grid_v[i, j].x = 0if j < bound and grid_v[i, j].y < 0:grid_v[i, j].y = 0if j > n_grid - bound and grid_v[i, j].y > 0:grid_v[i, j].y = 0

4.3.4 G2P

mpm88.py Line 55, 72:

    for p in x:Xp = x[p] / dxbase = int(Xp - 0.5)fx = Xp - basew = [0.5 * (1.5 - fx)**2, 0.75 - (fx - 1)**2, 0.5 * (fx - 0.5)**2]new_v = ti.Vector.zero(float, 2)new_C = ti.Matrix.zero(float, 2, 2)for i, j in ti.static(ti.ndrange(3, 3)):offset = ti.Vector([i, j])dpos = (offset - fx) * dxweight = w[i].x * w[j].yg_v = grid_v[base + offset]new_v += weight * g_vnew_C += 4 * weight * g_v.outer_product(dpos) / dx**2v[p] = new_vx[p] += dt * v[p]J[p] *= 1 + dt * new_C.trace()C[p] = new_C

J p − n e w = J p ( 1 + ( C 00 + C 11 ) Δ t ) J_{\bold{p}-new} = J_{\bold{p}}(1 + (\bold{C}_{00} + \bold{C}_{11})\Delta t) Jpnew=Jp(1+(C00+C11)Δt)

Note

  • C 00 \bold{C}_{00} C00 C 11 \bold{C}_{11} C11 同样可以用来表示粒子的膨胀(正值)和收缩(负值)。

screenShot.png

参考课程

文中相关资源来自课程:

  • [Chinagraph 2020] 用太极编写物理引擎 (5) 物质点法

这篇关于【GAMES201学习笔记】物质点法入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/249953

相关文章

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学