我个人对基于物理的动画很感兴趣,最近在尝试阅读《Fluid Engine Development》,由于内容涉及太多的数学问题,而单纯学习数学又过于枯燥,难以坚持学习(我中途放弃好多次了),打算尝试通过编写博客总结知识的学习方法来学习。

在计算数值问题时,我们经常遇到线性方程,比如基于网格的流体模拟在求解扩散和压强,需要求解线性方程组。

线性方程组

线性方程组 \(\left\{ \begin{matrix} 2 * x - y =3 \\ -x + 2 * y = 6 \end{matrix}\right\}\)​

可以转换成形如 \(A \times x=b\) 的矩阵矢量形式,转换结果如下

$\left[
\begin{matrix}
2 & -1 \
-1 & 2
\end{matrix}
\right] \left[
\begin{matrix}
x \
y
\end{matrix}
\right] = \left[
\begin{matrix}
3 \
6
\end{matrix}
\right] $

其中A是系统矩阵,x 为所求解,b是一个矢量,也就是线性方程的常数项

至于如何求解x,通常我们是通过 是让等式两边乘以系统矩阵的逆矩阵

高斯消元法

求解线性方程组我们通常使用高斯消元法来求解逆矩阵,这种方法虽然足够直接,然而把高斯消元法作为一种算法来看待,这种算法的时间复杂度达到了惊人的 \(O(n^3)\),n是矩阵的尺寸,由此我们可以明确高斯消元法并不适合有着许多数值问题的较大系统。

如果不选用高斯消元法直接求解逆矩阵,如果不通过高斯消元法,我们又该通过什么方法计算逆矩阵呢?《Fluid Engine Development》给出了就4种不那么直接的方法。通过对解的猜测和多次迭代得到近似解

雅可比方法

雅克比方法(Jacobi方法)是用于确定对角占优的解的迭代算法。求解每个对角元素,并插入近似值。然后迭代该过程直到它收敛

使用雅克比方法,需要将\(A \times x=b\) 转换成 \((D + R) \times x=b\) (矩阵A被拆成对角矩阵D和矩阵R)

所以易得解\({x}^{(k+1)} = D^{-1} (\mathbf{b} - R \mathbf{x}^{(k)})\) k是迭代的次数

同样作为矢量的解的每一个元素可以通过$ x^{(k+1)}i = \frac{1}{a{ii}} \left(b_i -\sum_{j\ne i}a_{ij}x^{(k)}_j\right),\quad i=1,2,\ldots,n.$计算得到

Gauss-Seidel法

Gauss-Seidel方法和jacobi方法有些像

将\(A \times x=b\) 转换成 \((L + U) \times x=b\) (矩阵A被拆成包含对角部分的下三角形和又矩阵A上三角形部分构成的矩阵U)

具体如下

$\left[
\begin{matrix}
2 & -1 \
-1 & 2
\end{matrix}
\right]= \left[
\begin{matrix}
2 & 0 \
-1 & 2
\end{matrix}
\right]+ \left[
\begin{matrix}0 & -1 \
0 & 0
\end{matrix}
\right] $

通过这种形式的转换我们可以轻易的发现解的第一个元素能轻易的被计算出来

$ x^{(k+1)}1 = \frac{1}{a{11}} \left(b_1 -\sum_{j>1}a_{1j}x^{(k)}_j\right)$

将上式代入第二行,我们可以得到$ x^{(k+1)}2 = \frac{1}{a{22}} \left(b_i -a_{21}x_{1} ^{k+1}-\sum_{j>1}a_{1j}x^{(k)}_j\right)$

然后可以得到同样的迭代解 \(x^{(k+1)}_i = \frac{1}{a_{ii}} \left(b_i - \sum_{j=1}^{i-1}a_{ij}x^{(k+1)}_j - \sum_{j=i+1}^{n}a_{ij}x^{(k)}_j \right),\quad i=1,2,\dots,n.\)

梯度下降法

梯度下降法将线性方程组求解问题转换成求解最小值问题 \(F(x) = |Ax - b|^{2}\)

如果x有解,则F(x) = 0,如果无解,则可以一直迭代直到x有解,

如果从x1开始,沿着梯度下降,逐步迭代来靠近零点

共轭梯度法

相对梯度下降法,共轭梯度法不使用梯度方向迭代,而是使用共轭方向

何为共轭,如果 \(a *( A b) = 0\) 则我们称向量a,b关于矩阵A 共轭

预处理共轭梯度法

在此基础上,我们可以进一步加速: 这个方法称为预处理共轭梯度法。大体的思想是,引入一个preconditioning filter到系统中:

\(M^{-1}Ax = M^{-1}b\)

具体算法实现如下

d就是新的共轭方向,alpha的推导参考链接

《Fluid Engine Development》 学习笔记1-求解线性方程组的更多相关文章

  1. 《Fluid Engine Development》 学习笔记4-预测校正不可压缩SPH-PCISPH

    传统SPH方案的主要问题之一是时间步长限制.在原始的SPH中,我们首先从当前设置计算密度,使用EOS计算压强,应用压力梯度,然后运行时间积分.这个过程意味着只需要一定的压缩量就可以触发内核半径内的压力 ...

  2. 《Fluid Engine Development》 学习笔记2-基础

    断断续续花了一个月,终于把这本书的一二两章啃了下来,理解流体模拟的理论似乎不难,无论是<Fluid Simulation for Computer Graphics>还是<计算流体力 ...

  3. 《Fluid Engine Development》 学习笔记3-光滑粒子流体动力学

    用粒子表示流体最热门的方法就是就是光滑粒子流体动力学(Smoothed Particle Hydrodynamics (SPH).) 这种方法模糊了流体的边界,用有限数量的粒子代表流体,该方法的基本思 ...

  4. matlab学习笔记之求解线性规划问题和二次型问题

    一.线性规划问题 已知目标函数和约束条件均为线性函数,求目标函数的最小值(最优值)问题. 1.求解方式:用linprog函数求解 2.linprog函数使用形式: x=linprog(f,A,b)  ...

  5. Foundations of Qt Development 学习笔记 Part1 Tips1-50

    1. 信号函数调用的时候仅仅会发送出信号,所以不需要执行 ,所以对于信号声明就行,但是不需要进行定义. 2. 只有槽函数可以声明为public,private,或者是protected的,而信号不行. ...

  6. 扩展中国剩余定理(EXCRT)学习笔记

    扩展中国剩余定理(EXCRT)学习笔记 用途 求解同余方程组 \(\begin{cases}x\equiv c_{1}\left( mod\ m_{1}\right) \\ x\equiv c_{2} ...

  7. Sparse Filtering 学习笔记(三)目标函数的建立和求解

      Sparse Filtering 是一个用于提取特征的无监督学习算法,与通常特征学习算法试图建模训练数据的分布的做法不同,Sparse Filtering 直接对训练数据的特征分布进行分析,在所谓 ...

  8. GMM高斯混合模型学习笔记(EM算法求解)

    提出混合模型主要是为了能更好地近似一些较复杂的样本分布,通过不断添加component个数,能够随意地逼近不论什么连续的概率分布.所以我们觉得不论什么样本分布都能够用混合模型来建模.由于高斯函数具有一 ...

  9. Chrome development tools学习笔记(5)

    调试JavaScript 随着如今JavaScript应用的越来越广泛,在面对前端工作的时候,开发人员须要强大的调试工具来高速有效地解决这个问题.我们文章的主角,Chrome DevTools就提供了 ...

随机推荐

  1. 批量清理harbor镜像

    #! /bin/bash # 通过Harbor提供的API来批量删除镜像,人工删除费时费力 # 经过测试发现,通过接口去删除时提供的是的标签,但实际上删除的时候通过的是镜像的IMAGE_ID,也就是说 ...

  2. 学到了林海峰,武沛齐讲的Day16完

    函数嵌套 foo()()() ====  foo()>>>gxr   gxr()>>>wsb    wsb()>>执行wsb函数 lambda   一行 ...

  3. 超过20g的文件+上传

    demo下载地址:jsp-Eclipse,jsp-MyEclipse,PHP,ASP.NET 教程:ASP.NET,JSP,PHP 一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件 ...

  4. bochs调试命令

    Bochs几条基本指令: 通过物理地址查看内存时,可以不加参数'/nuf': 其中n指定显示的单元数,默认是1: u 指定每个显示单元的大小(b表示字节.h表示字(2字节).w表示双字(4字节)),默 ...

  5. codeforces524E

    题意:n*m的矩阵,给出k个点,Q次询问,问每个矩阵中每个点是否被看管,一个点被看管的定义是那个点所在的行或列有点,n,m<=1e5,k,q<=2e5 sol :发现行和列是独立的,即要么 ...

  6. 内存分析工具 MAT 的使用【转】

    转自:http://blog.csdn.net/aaa2832/article/details/19419679/ 1 内存泄漏的排查方法 Dalvik Debug Monitor Server (D ...

  7. Mybatis使用IN语句查询

    一.简介 在SQL语法中如果我们想使用in的话直接可以像如下一样使用: select * from HealthCoupon where useType in ( '4' , '3' ) 但是如果在M ...

  8. mysql中查询某个字段重复的数据

    SELECT corp_name,count(*) as sums FROM corp_tax WHERE corp_year = 2018 AND corp_month = 8 group by c ...

  9. C语言中的指针笔记

    C语言指针 得到变量的地址 可以使用&运算符找到变量保存在内存中的位置 int x = 1; printf("x的内存地址是"%p\n",&x) %p格式 ...

  10. 咏南中间件D7客户端演示

    咏南中间件D7客户端演示 咏南中间件MORMOT(http.sys)支持D6.D7等老版本开发客户端.客户端使用TClientDataSet内存表控件,数据序列使用TynSerial类.