使用八叉树模拟水和烟雾 Simulating Water and Smoke with an Octree Data Structure 论文阅读笔记

原文:

Losasso, Frank, Frédéric Gibou, and Ron Fedkiw. “Simulating water and smoke with an octree data structure.” Acm siggraph 2004 papers. 2004. 457-462.

引言

这篇文章扩展了 [Popinet 2003] 的工作,拓展到表面自由流,并且使得八叉树不受限制

自适应网格划分的一个缺点是,它的模板不是均匀的,进而导致泊松方程中的系数矩阵是非对称的

我觉得他这个模板的意思就是,离散化速度的二阶导的这个离散的模板吧
或者说是格式?
比如对于最简单的均匀网格,对于某一个网格,考虑它的前后左右上下,因为是对称的,所以只需要三个方向,up right front 三个变量。以自己为中心,自己有一个 center 变量。所以构建矩阵的时候,每一个网格都有自己的一套 up = 0 right = 0 front = 0 center = 1。如果上方向是流体,那么 up = -c, center += c。这种模板?

[Popinet 2003] 对于这个非均匀的方程组是使用多级泊松求解器来求解的

但是 [Day et al. 1998] 指出这种方法在处理具有高频细节的物体的时候存在问题

这种方法也难以处理界面,比如空气与水的界面

本身界面的准确表达就是很困难的

[Suss-man et al. 1999] 提出了在界面处涂抹密度的方法(听起来这个涂抹就是一种混合?)

界面上的波是由压力差导致的,这种涂抹就是在减小高频的压力差,所以会消除细节

这篇文章坚持使用八叉树作为自适应方法,虽然一般情况下这会导致非均匀的泊松方程组,但是这篇文章使用了特殊的设计,根据这种设计,他们得到的泊松方程仍然是对称正定的

虽然“使用了特殊的设计”并不是它的原话,但是我觉得他是这个意思?

以往的工作

求解 NS 方程,半拉格朗日求解平流,火、云、粒子爆炸、粘性流、气泡和表面张力、水花和泡沫

SPH

八叉树上的 SDF

SDF 的重新初始化

速度外推

半拉格朗日法求解水平集可能耗散比较大,导致质量损失严重

粒子水平集法的耗散可能更少

使用四叉树的水平集演化

但是这些研究都没有考虑到水的界面

水的界面,不就是水平集的一个应用吗?有点不理解

自适应网格细化 adaptive mesh refinement (AMR) 通常使用多个不同分辨率的网格,重叠在一起

一开始这是为了研究激波的,所以块状结构能够减少切换网格层次所带来的伪激波反射

但是,如果不考虑激波,那么就可以使用不受限的八叉树

这里讲的是它的灵感来源?

八叉树

压强存储在格子中心,速度存储在面上(MAC 网格),其他标量存储在格子节点

他说使用节点存储标量很方便,因为它的插值方便(我怎么不觉得)

在这里插入图片描述

粗粒化是把小单元合并成大单元

在这个过程中,节点中的旧值,要么被删除,要么保持不变;面上的旧值经过平均赋给新值

我一开始想,这里讲的“节点中的旧值”,包不包括网格中心上的值?

在这里插入图片描述

画了一下,八个块变成一个块,最后的大块的中心的那个压强应该是平均来的才对,之前那个位置是存别的标量的顶点的位置……所以他指的“节点中的旧值”应该是不包括网格中心的值

那他这里就说少了一个情况啊……算了

细化是从一个大单元细分成多个小单元。边的半点上的值来自两端顶点的平均值,面中心的顶点的新值来源于这个面的四个角点的平均值。细分后的面上的速度,是来源于细分后的顶点上的速度的平均。而细分后的顶点上的速度,来源于他周围四个细分前的面的平均。

这个"细分前"、"细分后"定语都是我自己加的
我觉得这个细分后的顶点上的速度的来源很奇怪啊,不是所有细分后的顶点都是周围四个面,也有周围两个面的。那对于这个两个面的,是不是只是两个面的速度的平均?
下面是我画的,获得细分后的顶点上的速度的两种情况的示意图

在这里插入图片描述

对于所有变量,我们将边上的 T 形连接节点约束为从该边上的邻居进行线性插值。类似地,面上的 T 形连接节点被限制为周围四个角值的平均值。参见,[Westermann et al. 1999]

这个是真的有点难理解,只好机翻了

八叉树上的 NS 方程

散度算子

泊松方程

∇ 2 p = ∇ ⋅ u ∗ / Δ t \nabla^2 p = \nabla \cdot u^* / \Delta t 2p=ut

他把泊松方程应用在体积上,得到

V c e l l ∇ 2 p = V c e l l ∇ ⋅ u ∗ / Δ t V_{cell} \nabla^2 p =V_{cell} \nabla \cdot u^* / \Delta t Vcell2p=Vcellut

不知道怎么就这样直接得到的

或许他是默认,对于整个体积,物理量都是一样的,所以相当于 ∫ 1 d V = V \int 1 dV = V 1dV=V

然后他说用格林公式,或者说是高斯公式吧?把体积分转换成面积分

这里就是它处理八叉树的部分了,我猜,不同分辨率的网格的相接可以转换为一个大的网格面和多个小的网格面的重叠,这样的情况?

现在等式左右两个都可以这么转换。只看对于速度散度的转换,相等于考虑一个散度算子。转换成面积分的话,只有垂直于面的分量才有效,所以速度乘以了一个法向量

然后我猜他是要强调处理一个大面和多个小面的重叠,所以才不写成 ( u f a c e ⋅ n ) A f a c e (u_{face} \cdot n) A_{face} (ufacen)Aface

而是写成求和的形式

V c e l l ∇ ⋅ u ∗ = ∑ f a c e s ( u f a c e ⋅ n ) A f a c e V_{cell} \nabla \cdot u^* = \sum_{faces} (u_{face} \cdot n) A_{face} Vcellu=faces(ufacen)Aface

重新看他画的网格

在这里插入图片描述

后面他印证了我的想法,这么写就是为了适应一个面和多个小面重叠的情况

在这里插入图片描述

然后导数就可以把大面和小面联系起来,真的很奇妙,虽然从泰勒展开的直接上是消掉了常数项,但是不知道为什么就这么直接得到了

然后压强的拉普拉斯算子的转换到面积分的过程,只是在压力梯度上套用散度算子

在这里插入图片描述

压力梯度

在这里插入图片描述

如果是两个大小相同的,那么就是压强梯度 py

如果是为了在网格 1 和 2 之间的话,那么首先在 p1 和 p10 之间插值得到 pa,然后在 pa 和 p2 之间得到压强梯度 px hat

但是 px hat 不在面上,所以可能会采用更加复杂的离散化的方法,比如使用 pa p2 p6 来构造压强梯度,例如 [Chen et al. 1997]

但是这种复杂的离散化方法就导致了泊松方程的非对称性

因为 1 和 2 之间的压强梯度会依赖于 p10 和 p6,这就是明显网格 1 依赖于某一个方向上的压强了。相反地,网格 6 不太可能依赖于网格 1,因为网格 6 已经和一个相等大小的网格 2 并列了。即使依赖了,也不会对称

之后感觉是精华的部分,就是他为了消除这种依赖,进而得到对称的结构所做的事

之前说 px hat 不在面上,所以采用了更加复杂的离散化措施,这是一个导致不对称性的原因。所以现在他就干脆不用复杂的离散化措施,就直接令 px hat 代表面上的压强梯度,也就是网格 1 与网格 2 之间的压强梯度

然后不对称性的第二个原因是 pa 由 p1 和 p6 插值,会依赖 p6。那么他就直接令 pa = p1,不要这个插值了

经过这一通化简,计算网格 1 和网格 2 之间的压强梯度就只用到网格 1 和 2 的压强了

他这里就认为,引入了 O ( Δ x ) O(\Delta x) O(Δx) 级别的误差是可以接受的

那么现在网格 1 和网格 2 之间是对称的了

现在泊松方程组就是对称的了

准确度

他认为半拉格朗日平流是一阶,现在压强求解是一阶,也只是两个的精度相同

但是它的测试是精度还是挺好的

烟雾

总结

后面的都无关紧要了

总之他这个文章的核心就是,现在八叉树的两个网格就只考虑彼此,暴力忽略其他网格,就这么得到了对称的模板

忽然发现称为模板隐含着一个很优雅的事情,就是它可以包括某个点是流体或者是固体的情况

这样,我们只需要最后讨论一下边界条件怎么放进来就好了,一开始推公式的时候就不用想边界

好酷啊

在这里插入图片描述

总之好羡慕啊,我现在的心情就跟我第一次看到半拉格朗日平流的 stable fluid 一样,感觉这么简单但是有效的东西,他们就能够研究到,然后发出来,就很优雅,很有应用上的美感的这么一件事

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-19 06:50:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-19 06:50:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-19 06:50:03       87 阅读
  4. Python语言-面向对象

    2024-02-19 06:50:03       96 阅读

热门阅读

  1. Python Web开发:Django与Flask框架

    2024-02-19 06:50:03       52 阅读
  2. vue自定义view,传值和事件回调

    2024-02-19 06:50:03       49 阅读
  3. mongodb常用命令

    2024-02-19 06:50:03       47 阅读
  4. ACM/NOI/CSP比赛经验分享

    2024-02-19 06:50:03       48 阅读
  5. 阿里云香港服务器是cn2线路吗?

    2024-02-19 06:50:03       63 阅读
  6. 目标检测中AP50 AP75 APs APm APl 含义

    2024-02-19 06:50:03       50 阅读