【遊戲流體力學基礎及Unity代碼(一)】熱傳導方程

2021-01-18 Unity3D遊戲開發精華教程乾貨

在遊戲中模擬流體並不是什麼新鮮事,但是我幾乎就沒看到什麼好的入門文章。有些文章用尖峰波或者FFT模擬,但那畢竟是統計學方法,和流體力學還是不搭邊。其餘的文章倒是用了納韋斯託克方程,但那也僅僅是把納韋斯託克方程寫了一遍,好一點的還給仍你一些居複雜的代碼,對我等入門者來說實在是看不懂。

最近我在github上找到三個不錯的python jupyter notebook庫

1.首先是大名鼎鼎的12步納韋斯託克方程,oschina上有中文翻譯,油管上python版本和matlab版本的對應編程視頻

https://github.com/barbagroup/CFDPython

2.然後是格子波茲曼方法,也是除了納韋斯託克方法外的一個經典方方法

https://github.com/pylbm/pylbm

3.然後這個空氣動力學python庫,雖然說是空氣動力學,但和流體力學相同的地方很多

https://github.com/barbagroup/AeroPython

於是這個「遊戲流體力學基礎」系列將在這些庫的幫助下,從最基本的方程開始推導,儘量保證貓都都能看懂,來完成遊戲中的流體模擬吧!預計會有十幾篇。

好了,我們開始學習一些基本的火系魔法知識吧!【誤】



首先我們看一個這樣的問題,對於一個一維物體,如果它的左端點溫度是700度,右端點溫度是300度,並且這個物體上的溫度是連續均勻變化的,那麼這個物體的其它位置的溫度是多少?

當然,由於計算機只能求解離散的物體,我們需要將問題轉化成如下形式,將一個物體分成八格,每格都有一個自己的溫度值。如果最左邊一格的溫度是700度,最右邊一格的溫度是300度,並且每格之間的溫度變化也是均勻連續的,那麼中間六格的溫度各是多少?



你會說,這還不簡單嘛,不就是解一元一次方程嘛。但是這僅僅是一維的情況,並且我們確定的溫度值只有兩個而已。如果到了三維,並且確定的溫度值有很多個的時候,要求解的溫度值也很多的時候,要通過解析方法求解就很麻煩了。我們得換個法子。

既然我們不知道中間六格的溫度,我們就瞎猜嘛,說不定猜對了呢?

我們猜中間六格的溫度都是0度。嗯,結果顯然看起來不太對,但我們可以改一下。除了我第一格和第八格的溫度已經給定不能再改變外,其它六格的溫度我們都可以繼續改,讓結果看起來更加合理一些。



牛頓爺爺說過,當兩個互相接近的物體溫度不相等的時候,它們的溫度肯定會被互相影響。也就說,第二格的溫度會因第一格和第三格的溫度的影響而改變,第三格的溫度會因為第二格和第四格的溫度的影響而改變....但具體會如何被影響呢?

某個方格的值會被附近方格的值影響,是不是很熟悉?對啦,高斯模糊就是用的這種方法!



簡單起見,我們就設第二格的溫度等於(第一格的溫度 加上 第三格的溫度)除以二。於是經過一次計算後,每個方格的溫度就變成了下面的樣子。



顯然結果看起來還是不太對。但是,熱量會持續傳導,時間會見證一切。


可以看到在第100秒,方格之間的溫度差是57度左右,拿出除法一算,400 / 7 大約也是57度,很不錯的。實際上第50秒的結果已經很接近第100秒的結果了,所以如果對精度要求不那麼高,那麼就算100次就結束吧。

既然我們的瞎猜法很不錯,那麼我們就要總結經驗,把瞎猜法發揚光大。不過我們之前說的:「第二格的溫度等於(第一格的溫度 加上 第三格的溫度)除以二」 這句話太長了,我們將其轉換為數學語言:



其中T就是溫度,下標n代表第n個方格,t代表第t秒。然後我們就可以得到第n個方格第t+1秒的溫度和第t秒溫度之間的關係:

不過上面這個公式還不夠簡潔,讓我們將其寫為人看不懂的形式吧:

dt即時間的跨度,我們之前將其設置為1秒,也就是1。dx就是空間的跨度,也是不同網格之間的距離,我們之前將其設置為1格,也就是1。這裡,時間t只有一階導數是因為時刻t的溫度只受到t-1的溫度的影響。而x為二階導數是因為,第n個格子會受到n-1和n+1兩個格子的影響。

然後我們將這個公式寫得更加簡潔一些,然後取個名字,就叫一維熱傳導方程吧:

這裡的a就是一個迭代參數,我們之前將其設置為1/2。實際上可以設置得更小,也就是熱傳導速度更慢,防止出現一些莫名奇妙的結果。當然這樣求解起來也就更慢了。如果大於1/2,那麼就會出現不穩定的狀態,比如將其設置為0.7,僅僅第三次迭代後第二個網格的溫度就高於730度了,產生不穩定狀態的原因也很好理解,第三格實際上不能把0.7的熱量同時分配給第二格和第四格,第三格沒那麼高的溫度。

好了,現在你可以拿這個公式去欺負那些沒見過世面的麻瓜了!記住把式子改成下面的樣子讓他們更加看不懂,其中三角形是拉普拉斯算子,u是待求解的量,我們這裡就是溫度。

不過這個的一維熱傳導方程是否還能寫成別的形式呢?

比如我們要測量b處的溫度變化速度,而a處的溫度會影響b處,它們之間的關係應該是怎樣的呢?首先它們之間會有一個介質,介質面積越大,熱傳導速度越快,熱量變化速度也越快,這就是面積A。介質厚度越大,熱量變化越慢,這就是厚度dx。a處和b處的溫度差越大,溫度變化也越快,這就是溫度差Ta - Tb。除了這個三個因素外,介質的材質參數k也會影響溫度變化速率,如下圖所示。

根據傅立葉法則,我們得到熱傳導方程為如下形式

其中等式左邊是熱量的變化速度。所以對於之前的迭代參數a來說,它的實際物理意義是材質參數乘上介質面積。



先廢話兩句。其實這種模擬流體的代碼通常寫在Python和Matlab和Foratan上,上github上一搜一大把,當然看不看得懂就是另一回事了。但是由於看這篇文章的讀者對unity更加熟悉一些,而且很方便移植到opengl/directx上,所以就用unity寫了。順便吐槽一句unreal寫著色器太麻煩了。

看懂下面的內容需要一點unity著色器的知識,如果你沒有,現在立馬去把那本《UnityShader入門精要》吃掉。

我們在著色器上實現的方法現在很簡單,就是在攝像機上掛一個全屏處理腳本,直接把著色器生成的材質放到整塊屏幕上。

我們需要三個RenderTexture,第一個_rtNull是全黑的紋理,也就是初始狀態溫度全為0,此時還沒有設置邊界條件。

第二個_rt0代表上一幀的結果,經過計算後得到本幀的結果_rt1,再將後者輸出的屏幕上。最後再將rt1複製給rt0,用於下一幀的計算。

下面是要掛到攝像機上的代碼,之後我們會將_TexelNumber設置為8,也就是方格的數量。同時將每秒的幀數設置為2,方便我們動態觀察。

public class FullScreen : MonoBehaviour{    
public Material _mat; public RenderTexture _rtNull; public RenderTexture _rt0; public RenderTexture _rt1; [Range(2,100)] public int _TexelNumber;
private void Start() { Graphics.Blit(_rtNull, _rt0); Application.targetFrameRate = 2; _TexelNumber = 8; } private void Update() { _mat.SetInt("_TexelNumber", _TexelNumber); _mat.SetTexture("_MainTex", _rt0); }
private void OnRenderImage(RenderTexture source, RenderTexture destination) { Graphics.Blit(_rt0, _rt1,_mat); Graphics.Blit(_rt1, destination); Graphics.Blit(_rt1, _rt0); }}


然後在資源管理器中創建這三個RenderTexture,然後拖到腳本上即可。注意RenderTexture大小要改成和輸出屏幕一樣大小。

我們現在不用修改頂點著色器,所以下面是像素著色器的代碼,原理和高斯模糊很類似,採集上一幀圖像中左邊網格的值和右邊網格的值再平均,就得到新的溫度值。

float  _Temprature  = 0.0f;float  _TexelSize  = 1.0f / _TexelNumber;if ( i.uv.x < _TexelSize )  _Temprature = 0.7f;else if ( i.uv.x >= 1 - _TexelSize )  _Temprature = 0.3f;else{  float2  leftuv  = float2( i.uv.x - _TexelSize, i.uv.y );  float  leftT  = tex2D( _MainTex, leftuv ).g;  float2  rightuv = float2( i.uv.x + _TexelSize, i.uv.y );  float  rightT  = tex2D( _MainTex, rightuv ).g;  _Temprature = (leftT + rightT) / 2.0f;}return(float4( 1.0f, _Temprature, 0.0f, 1.0f ) );

最後Return語句的原理如下。我們假設我們模擬的世界中,溫度的顏色如下變化

於是,我們就可以將RGB中的R設置為1,B設置為0,僅將G作為變量。當G從0到1變化時,我們就假設溫度從0度到1000度變化,於是顏色就也如上圖變化。點擊,播放,現在場景看起來如下,大約過了十秒左右顏色變化就不太明顯了。如果把_TexelNumber改得更大一些,那麼迭代需要的時間也更久。

是不是很簡單?現在你已經初步掌握了火系魔法的要點,快用爆裂魔法去和魔王軍首領對決吧!相信你一定可以的!【誤】



之前說過我們的瞎猜法,在一維的情況下,就是左邊格子和右邊格子的平均值。那麼在二維情況下怎麼辦?你肯定已經想到了,就是上下左右四個格子的平均值!三維就是上下左右前後六個格子的平均值,就這麼簡單。

但不僅僅能取上下左右四個格子,對角線上四個其實也可以取,就連要求解的格子本身也可以取上一幀的值,不過要乘上一些不同的權重。這就是格子波茲曼方法,lattice boltzmann method。這個我們之後的篇章再討論。

寫成離散化形式就是如下:

二維代碼和三維方程我就不貼了。就把它當作一個挑戰留下來吧。值得注意的是我們這裡的dt,dx和dy都是1,而a也僅僅是簡單的權重,所以算是大大簡化了這個方程。三維方程代碼編寫方式更加複雜一些,我們之後的篇章再討論。

我將左下角溫度設置為700度,右上角300度,右下角0度,最後得到這樣的圖。

現在我們已經會搓小火球了,接下來我們正式開始學習如何搓水球,下一篇文章《用平流方程模擬染料流動》:

宣傳:我創建了一個模擬流體交流Q群,歡迎各位喜歡自己編寫代碼模擬流體的小夥伴們入群互相交流學習!群號:1001290801。


聲明:發布此文是出於傳遞更多知識以供交流學習之目的。若有來源標註錯誤或侵犯了您的合法權益,請作者持權屬證明與我們聯繫,我們將及時更正、刪除,謝謝。

作者:光影帽子

原文:https://zhuanlan.zhihu.com/p/263053689


More:【微信公眾號】 u3dnotes





相關焦點

  • 【遊戲流體力學基礎及Unity代碼(二)】用平流方程模擬染料流動
    寫出一個簡潔的數學公式,也就是一維平流/對流方程 等式左邊就是此網格下一時刻染料粒子密度相較於這一時刻的增長,而右邊a就是速度,偏微分代表此時刻此網格與前一個網格的密度差。真實世界中,dt和dx都是無窮小的,所以上面這個公式是絕對精確的。為了獲取一維平流方程的精確離散形式,我們要用到泰勒展開。你可以在各種高等數學書上找到泰勒展開的定義。
  • 【遊戲流體力學基礎及Unity代碼(四)】用歐拉方程模擬無粘性染料之公式推導
    最後,1式等式左邊動量可以用下面這個式子表示: 單位時間內動量的變化就是 集齊2~5這四個式子,就召喚出了流體力學三大基本守恆方程之一——動量方程。聯合起來,就得了歐拉方程: 歐拉方程與NS方程唯一的區別就是,歐拉方程沒有計算流體的粘性,而NS方程計算了流體的粘性。也就是歐拉方程 = 重力 + 壓力NS方程 = 重力 + 壓力 + 粘性力但這裡我們把重力省略,而加上了來自滑鼠拖動產生的力。
  • 流體力學NS方程推導
    自然界中宏觀情況的流體運動畢竟佔據大多數,NS方程限定了自己的適用條件為宏觀運動,採用稍微專業一點難度術語是流體滿足連續介質假設。連續介質假設成立需要滿足:所研究流體問題的最小空間尺度遠遠大於分子平均運動自由程(標準狀況下空氣的平均分子自由程在十分之一微米的量級,具體值可以參考分子運動理論),這在大多數宏觀情況下都是成立的,也是NS方程能夠廣泛採用的基礎,即使在湍流中
  • unity遊戲製作初始人物控制代碼
    大家好,今天小編帶大家學習一哈unity遊戲製作中初始人物控制代碼。1.我們知道遊戲中,選中人物,在人物未開始運動前,往往會有一個初始的動作,好的,我們這節課通過unity中相關代碼和基礎設置來實現這一效果。
  • 熱傳導方程的差分格式原理與matlab實現
    熱傳導方程的差分格式一、研究問題介紹拋物型方程中一種最基本形式
  • 用歐拉方程模擬無粘性染料之代碼實現
    但這個解決我們在第一章就說過了,我們雖然一開始不知道確切值,但我們可以猜嘛,多猜幾次就和正確結果差不多了。所以1式右邊是壓力就是上次猜的結果,左邊的壓力就是這次的結果。上面那個例子寫成C++代碼如下,貼到main函數裡即可運行。下面這段代碼實際上是錯的,並不能正確求得壓力,因為沒考慮邊界情況。但是看看下面的代碼至少能讓你對大體求解方法是怎樣的有個直觀的印象。
  • 基於熱傳導能量方程的熱阻模型的建立
    一、建立預估熱阻模型的傳熱學理論基礎現今的傳熱學理論分為傳統傳熱學與新興的微納傳熱學。傳統傳熱學是在宏觀現象的研究中發展起來的研究熱量傳遞規律的一門理論,分析手段的是高等數學方法。因此必須建立在所研究的對象為連續體的假定上,即認為所研究的對象內各點的溫度、密度、速度等都是空間坐標的連續函數。
  • 波動方程 熱傳導方程 求解方法
    號那天考的全國大學生數學競賽(CMC賽)的令人振奮的消息(雖然沒有一等獎,但能得二等獎已經出乎我的預料了)以後還要繼續加油正文偏微分方程中波動方程和熱傳導方程的求解方法都是分離變量法分離變量法的思想貫穿著這兩種方程。甚至可以用分離變量法求解少部分的拉普拉斯方程。拉普拉斯方程的求解方法相比于波動方程和熱傳導方程更為複雜,需要採用更多的數學工具。這邊是一些關于波動方程以及熱傳導方程的求解例子。並不難,但是在計算積分的時候需要較為小心,爭取不要計算錯誤。
  • 超越198年前的傅立葉定律,終於揭示:熱傳播變得像流體一樣!
    這些「粘性熱方程」表明,熱傳導不僅與導熱係數有關,還與熱粘度有關。一般說來,這個公式很好地描述了高溫下宏觀(通常是一毫米或更大)物體中的熱傳導。然而,傅立葉熱方程未能描述所謂的流體動力熱現象。相比之下,在開發新的「粘性熱方程」時,研究人員將所有與熱傳導相關物理知識濃縮為精確且易於求解的方程。這為電子器件的設計,引入了一種新的基礎研究工具,特別是那些集成了金剛石、石墨烯或其他低維或層狀材料的電子器件,在這些材料中,流體動力學現象現在被認為是普遍存在的。
  • 流體力學野史
    這個公式講的是動量守恆和質量守恆兩個事情,歐拉巧妙的把守恆概念植入到流體力學之中,後世流體力學研究無論時空如何變化,守恆終生相伴。。。後來納維和斯託克斯兩位數學家發現這個剪切應力跟流體擴散現象有一腿,因此兩位一起集成了兩個克服闢邪劍法的絕招:粘性和散度。通過粘度和速度散度的乘積就可以得到剪切應力。  流體粘性早在100多年前就被牛頓基於實驗驗證,但是歐拉方程局限於三維空間無法體現粘性,因此歐拉方程也稱為無粘流體方程。
  • 流體力學學習筆記
    實驗方法能直接解決工程技術中的複雜流動問題,能發現新現象和新原理,實驗結果可用於檢驗理論分析或數值計算結果的正確性及應用範圍;理論分析方法包括對實際流動作適當簡化,建立正確的力學模型和恰當的數學模型,運用數學物理方法尋求流動問題的精確或近似解析解,明確地給出各種流動物理量之間普適的變化關係;
  • 流體力學主要理論模型
    嚴格來說這個方程組通常並不封閉,即方程中的未知數多於方程數。為了求出理論解,必須根據情況再提出一些符合或接近實際的假設,從而在某些條件下使方程組封閉。但是,即使方程組已封閉,求方程的解仍然不是輕而易舉的。
  • 熱導方程的Matlab數值解方法
    過冷水今天就和大家分享一下一維熱傳導方程特別案例的具體求解方法。熱傳導是一個很常見的現象。當物體內部的溫度分布不均勻時,熱量就會從溫度較高的地方流動,這個過程中,溫度是空間和時間的函數。熱傳導方程就是溫度所滿足的偏微分方程,它的解給出任意時刻物體內的溫度分布。
  • 熱傳導是怎樣的?傳導聲音嗎?
    小夥伴們,熱傳導在我們的生活中可以說無處不在。熱傳導是一中熱力學現象,它與聲音的傳導不同,如果單存制熱傳導,拿它與聲音事物關係的。一.熱傳導概念熱傳導是在一定媒介內的導熱現象。熱傳導按嚴格意義上來說,是指固體與固體的導熱現象。不過,也可以引申一步,那就是在液體,氣體或固體的導熱現象,我們都可以稱之為熱傳導。
  • 波動方程,了解下!
    聲學基礎上關於聲學波動方程的推導,來自理想流體媒質的三個基本方程,運動方程、連續性方程和物態方程(絕熱過程)。而關於流體力學也有三個方程,分別是質量守恆方程、動量守恆方程(N-S方程),以及能量守恆方程。事實上,在絕熱過程中,小擾動下的流體方程也可以推導出聲學方程。
  • 流體動力學NS方程的哲學缺陷
    事實上,理性力學家在1965年前後對於這個問題的看法是:在整個連續介質力學中,以本構方程來區別流體物質和固體物質是形式上協調的,但是在物質定義上是不協調的。間接的認為,流體的本構方程是非理性的。其中,Truesdell則明確的在其專著中表明靜水壓力項的存在是力學理論無法講清的,只能作為一個經驗項被動的接受下來。
  • 如何評價《太吾繪卷》的程序代碼?unity業餘愛好者說一下
    unity業餘愛好者說一下,這幾天傳的關於《太吾繪卷》代碼的事幾乎都是無中生有的事...一群用.net和vs做工程的人談論第三方引擎做的遊戲...真是雞同鴨講。太吾繪卷現在針對幾個常見誤會說一下1.只有一個main (x)unity的腳本都是依附於各個精靈的,沒有main,只有update2.沒有注釋(x)你反編譯出來的代碼有注釋
  • 印度科學家研製納米磁流體技術 可使熱傳導效率提高三倍
    > 印度科學家研製納米磁流體技術
  • 印度研製的納米磁流體技術可使熱傳導效率提高三倍
    印度英甘地原子能研究中心的科學家利用納米磁流體已經成功地將導熱效率提高了300%,這一研究成果達到世界先進水平。    該中心金屬材料研究實驗室John Philip博士說,納米磁流體有很大的市場前景,因為非常少量的流體就可以產生強大的製冷效果。這一技術對納米電子機械系統和微電子機械系統有重要意義。John Philip在穩定的膠體懸浮液中加入了半徑6.7納米的Fe3O4磁性納米微粒。
  • 關於熱傳導與熱應力有限元分析清單
    1、熱傳導理論基礎:1.根據能量守恆定律,可以建立熱傳導微分方程(拋物線型微分方程,傅立葉方程):