本篇介绍各种解决burgers方程的数值方法,相应的代码可在clatterrr/CFDcodepython找到。

上一章介绍了最简单的非线性方程,即一维无粘性burgers方程,但我们将它稍微改写一下

微分项用泰勒展开微分实际上得到了

上式是精确解。但是把右侧的值全算出来不现实。如果只取等式右侧第一项,就是有限差分(finite difference)形式的迎风格式(Upwind Scheme)。

一阶upwind格式的缺点就是舍弃了太多泰勒展开项,所以很不精确。而有限差分法规定每个网格由一个离散的值表示,在处理有关激波的不连续问题时并不那么自然,方便。所以有限体积(finite volume)法便被提了出来,这种方法将一个格子里的值看成连续的,从前到后积分后再除以格子长度就是格子的值,这种方法在处理不连续问题时有很大优势。比如最简单的有限体积法下的Lax-Friedrichs方法:

然而这种方法也只有一阶精度,并且有一些人工粘性(artifial viscosity)所导致的耗散(disspative)。它看起来像是这样的。虚线是准确的解,而其它颜色的线是不同情况下的Lax-Friedrhs。人工粘性就像高斯模糊样,让尖锐的部分变得平滑了,然而我们要模拟的激波也消失了,这显然不是一种很好的方法。

所以我们继续尝试新方法,即Lax-Wendroff方法:

Lax-Wendroff方法有二阶精度,并且人工粘性的影响非常小,二阶精度在大多数时候都够用了。其代码可在这里找到https://github.com/clatterrr/CFDcodepython/blob/main/RiemannSolver/Burgers1dLaxWendroff.py。与Lax-Wendroff方法很相似的MacCormack方法也经常被使用:

LaxWendroff和MacCormack都是二阶精度,看起来很方便好用,然而有着隐藏的问题,那就是振荡(oscillation)。它看起来像是这样的,虚线是准确的解,其它颜色则是在不同情况下的LaxWendroff方法,在临近激波的时候,虽然人工粘性几乎没了,但解的跳动非常严重,忽上忽下,偏离准确结果非常多。

振荡出现的原因也非常简单。比如我们要更新U_i的值,就要考虑它的U_i+1/2和U_i-1/2的值,这两个值又和U_i-1和U_i+1有关。所以U_i实际上的增加量,就是它自己的斜率,而斜率通过U_i-1和U_i+1计算出来。这就是问题所在。如下图,黑线是精确的解析解,而蓝线是近似的数值解。当U_i是全局最高值,理论上不能再有值比这个值高,而由于U_i-1小于U_i+1导致U_i的斜率为正的话,那么U_i+1/2会比U_i的值还要高,如下图,红线就是斜率,红点就是不该出现的高点,这就造成了振荡。

关于这个问题,油管上有三个非常不错的视频Need For Flux Limiter, Flux Limiters , How Does Flux Limiter Work,这三个视频的博主是同一人,似乎是MIT的教师,他的有关计算流体力学的其它视频质量也非常高,推荐关注。

如何消除这种振荡?Godunov直接采用一种非常简单的方法,也就是我们小学就学过的分情况讨论。比如对于下图,黑色箭头所指的位置,半个时间步后的值应该是多少?如果uL和uR都大于零,那么它们都会向右移动,那么结果就是uL。如下图的左下,浅蓝是初始位置,深蓝是半个时间步后的位置,深蓝画得有点偏为了方便比较。

最终的五种情况如下:

这样极大值附近就不会出现比极大值还大的值了,极小值也是如此,振荡自然也就消失了。这就是一种Total Variation Diminishing方法,简称TVD方法,可以用于消除振荡。另一种分情况讨论的方法是Roe方法。标准的Roe方法要先线性化,算出一堆特征值和矩阵,然后再计算f,但本篇并不打算讨论这个,所以仅仅用一种简单的方法代替这个,也就是

上面的a其实就是上篇所说的激波的速度,因此也被称为Roe Speed。还有一种是HLL方法。

这就是早期人类用数值模拟驯服激波的珍贵方法。【误】

然而Godunov,Roe和HLL方法的准确度很差,都要先判断激波两侧的速度然后决定F的值。速度仅仅被划分为两个区间,即大于零或小于零,F也只能从一开始就设定好的几个结果中选一个,因此只有一阶精度。能不能不要这么一刀切,而是根据向前速度与向后速度的比例来确定最终的F呢?

我们要继续尝试新方法,也就是通量限制器(flux limiter),也叫slop limiter。比如对于之前的LaxWendroff方法,要计算半步长的U,实际上应该用网格中心的U,加上自己斜率乘以网格长的二分之一,向前的斜率由前一格的值减去这一格的值得到,也就是下式

那个phi,就是flux limiter。对于LaxWendroff来说,它永远是一,因此也导致了振荡问题,这样不好。所以要继续尝试不同的方法。比如一个叫flux limiter的方法。因此我们先定义向前的斜率与向后的斜率之比为r,用r来决定phi。简便起见,下面的数学公式用u来代替U - dt\dx*F。

继续分情况讨论,如果r < 0,也就是前后斜率的符号不一样,那就说明出现了局部最大值或最小值,我们不能让半步的值比局部最大值还大,也不能比局部最小值还小,那么就定义此时的斜率为零,也就是 phi = 0。如果向前的斜率与向后的斜率符号相同,比如都是正数,但前向的斜率绝对值略小,那么就要注意向前半步的值不能比前一格的值还要大,因为此时前一格可能是局部最大值。所以此时phi = r。如果向前斜率的绝对值比向后的更大,那么此时我们就使用laxWendroff所使用的phi = 1就行了,这就是minmod limiter。下图红线代表半步长的值。

表达式可以写成下面两种形式:

但实际写代码的时候更常使用下面这种函数的形式

除了minmod之外,还可以选择其它的flux limiter,最常用的如下:

上面的改进是基于LaxWendroff。但也可以使用另一种方法,也就是Monotonic Upstream-centered Scheme for Conservation Laws,简称MUSCL。它的就是在计算半步F的时候,不像之前那样使用此处的半步U,而且同时将而是把相邻网格所计算的此处的半步值也计算进来。

如下图,i+1/2处的值,即可以由左边U_i计算得到U^L,也可以由U_{i+1}计算得到U^R,而MUSCL方法将这两种值的影响都考虑了进来。

而将两个值都考虑进来后半步长F的具体算法,仍然可以由godunov或其它的flux limiter算法计算。比如由MUSCL + minmod来计算burgers方程,那么公式如下:

用上面介绍的所有方法解1dBurgers问题的代码都可以clatterrr/CFDcodepython找到。除了上面这些显式方法外,还有隐式方法也可以用,比如Runge-Kutta法,本篇不再介绍了。这些方法主要用来解决本系列第四篇提到的Euler方程,第七篇提到的Burgers方程,以及下一篇第九篇提到的浅水波方程。了解这些求解非线性方程的方法之后,就可以开始在unity上模拟了。

另外,我对一些概念理解还不够深入,所以本篇和代码可能有一些错误。还请大佬们发现后指导我一下。

宣传:我创建了一个模拟流体交流Q群,欢迎各位喜欢自己编写代码模拟流体的小伙伴们入群互相交流学习!群号:1001290801

参考

仅仅看我写的文章肯定是不够的,所以我选了一些不错的书籍列在下面

[1]《Computational Fluid Mechanics and Heat Transfer》 by Anderson, Dale Pletcher, Richard H. Tannehill, John C

[2]《Finite Volume Methods for Hyperbolic Problems》by Randall J. LeVeque

[3]《Handbook of Numerical Methods for Hyperbolic Problems Basic and Fundamental Issues》by Rémi Abgrall and Chi-Wang Shu

[4]《Riemann Solvers and Numerical Methods for Fluid Dynamics A Practical Introduction》 by Eleuterio F. Toro非常经典的书,超级推荐Riemann Solvers and Numerical Methods for Fluid Dynamics

[5]《Numerical Methods for Conservation Laws From Analysis to Algorithm》 by Jan S. Hesthaven

[6]《Solving Hyperbolic Equations with Finite Volume Methods》 by M. Elena Vázquez-Cendón 这书后面有一些代码可以参考

[7]《Numerical Solution of Hyperbolic Conservation Laws》by John A. Trangenstein

[9]《Exact solution of the Riemann problem for the shallow water equations》

[10]《计算浅水动力学——有限体积法的应用》谭维炎 著

推荐代码,包括了下一篇的浅水波方程。每一份都是经过精心挑选,简短而又清晰的适合初学者的代码~

flux unity 流体_【游戏流体力学基础及Unity代码(八)】激波捕捉法和RiemannSolver...相关推荐

  1. 帧差法matlab代码_【游戏流体力学基础及Unity代码(一)】热传导方程

    在游戏中模拟流体并不是什么新鲜事,但是我几乎就没看到什么好的入门文章.有些文章用尖峰波或者FFT模拟,但那毕竟是统计学方法,和流体力学还是不搭边.其余的文章倒是用了纳韦斯托克方程,但那也仅仅是把纳韦斯 ...

  2. qt 模拟鼠标滑轮_【游戏流体力学基础及Unity代码(四)】用欧拉方程模拟无粘性染料之公式推导...

    先放一张动态图吊一下胃口~下面就是最终的效果 不可压缩的欧拉方程只比NS方程少一个粘性项.所以下面的内容是完全适合NS方程的.各位请准备好! 散度定理 模拟流体的时候会遇到许多数学公式.为了深刻理解这 ...

  3. y空间兑换代码_【游戏流体力学基础及Unity代码(三)】用波动方程模拟三维落雨池塘,连续性方程...

    散度 最近要进行全国第七次人口普查啦,为了全社会的繁荣稳定,我们决定研究一下和水流很相似的人流的性质.假如有一个无限长的大厅,我们将它划分为很多方形区域.每个区域都有一些人,人可能会到处移动:如下图 ...

  4. java代码规范插件_「Java基础知识」代码规范插件怎么用

    原标题:「Java基础知识」代码规范插件怎么用 在开发中,好的编程风格可以提升团队合作能力,提升开发的效率,但是每个人都有自己的编程习惯,如何能够将大家的编程风格统一,这个在团队中也很重要; 在Jav ...

  5. unity 太阳自发光_unity shader基础之——unity中实现环境光、自发光

    上篇主要讲的是unity中的光照模型及其原理,还有几种光照类型(自发光.环境光.漫反射.高光反射),后面几篇文章就开始在unity中实现这几种光照类型,本篇在unity实现自发光.环境光. 一.uni ...

  6. unity粒子系统_【笔记】关于unity的粒子系统和UI之间的位置冲突解决

    终于解决了去年毕设解决的problem:主菜单的背景添加了Particle System,但是它总是跳到camera最前面挡住其他子菜单的Panel. 当时用的最土但最有效的办法:移动不同UI元素间Z ...

  7. Unity学习_我终于终于把unity音乐这块用单例控制得死死的了(1)!!!!

    两个脚本 AudioManager.cs(绑定在播放音乐的组件上,作用是不让其销毁,并且在场景切换一个循环回到初始场景是判断重复) using System.Collections; using Sy ...

  8. Unity 4.x 2D游戏开发基础教程

    淘宝网店购买地址:http://item.taobao.com/item.htm?spm=686.1000925.1000774.13.0Il2aP&id=39546154468 试读文档下载 ...

  9. unity 开发游戏 认识_认识明天鼓舞人心的Unity开发人员

    unity 开发游戏 认识 Whether making short animated films, cinematic experiences or games that tackle social ...

最新文章

  1. 中国城中村改造建设前景规划及投融资模式分析报告2022年版
  2. python从低到高排序_使用python对matplotlib直方图中的xaxis值从最低值到最高值排序...
  3. unity fixedupdate_unity相关
  4. Nodejs安装及使用
  5. javascript学习系列(21):数组中的reduceRight法
  6. 前端学习(1956)vue之电商管理系统电商系统之添加代码到仓库中
  7. 《C++字符串完全指南——第一部分:win32 字符编码》
  8. java vo转map_Java后端必备的开发规范
  9. 信息与通信工程学科面试准备——信号与系统
  10. 【其他】电脑ADB连接手机的方式
  11. 根据卫星星历计算卫星坐标——matlab app
  12. 【数据可视化作业】五个优秀可视化案例整理+Kaggle数据集useTableau实践
  13. 高德地图实现多天路线规划(途经点显示自定义内容)+轨迹回放(显示车牌)
  14. 大过 泽风大过 兑上巽下
  15. [bat] cmd命令进入用户登录界面和屏幕保护程序
  16. vue webapp之music(六)利用axios与后端接口代理请求歌单推荐数据
  17. SQL判断某列中是否包含中文字符或者英文字符
  18. MySQL - 对数据表进行“增删查改”的基础操作 - 细节狂魔
  19. 对自己的大学期望与目标
  20. 2019年架构软考论文押题(二)

热门文章

  1. 【DSY-2117】摩尔庄园
  2. nginx php 104,Nginx错误:recv() failed (104: Connection reset by peer) whi
  3. 新人必读!五分钟搞懂通信行业!
  4. win10系统自带查询电池健康命令
  5. 海康卫视网页端查看监控,一直提示下载插件问题
  6. 【SaaS架构】构建 SaaS 产品所需的技术——第一部分
  7. 2023年外贸行业面临的现状
  8. 非死不可?脸书华裔程序员跳楼自杀,刚刚38岁!
  9. java线程池的简单使用
  10. 基金定投的七大误区 影响你超过10%的年收益!