用浏览器做CFD
novakon2016/04/10软件综合 IP:广东
现代浏览器可以高效地运行js程序,可以方便的绘图,所以这次我用html+js,向大家示范一个简单的CFD程序。
QQ截图20160410143903.jpg

上面这个水池是最终效果。先别急,往下看。

=====这是分隔线=====

首先,我们要建立这池水的简化模型。
假设这池水,液面的垂直速度足够小(水面足够平缓),可以作如下简化:
1. 可以用一维数组,描述从左到右液面高度。
2. 液面只传递纵波。
3. 有黏度参数,“液柱”之间有损耗

首先要初始化液面高度数组,随便填充点啥吧
<code class="lang-js">var buffer = []
for(var i=0;i<128;i++){   buffer.push(.5*i); buffer init }< code></128;i++){></code>

仿真的每一步,都要计算多个参数,下面列出。

1. 液体在重力作用下,如果两个相邻的液柱有高度差,较高的液柱会受到向下的压力,较矮的液柱会受到向上的压力。简单的讲,设两个相邻液柱的液面高度差为delta_h, F 正比于 delta_h。
<code class="lang-js">
    //calculate force
    for(var i=0;i<buffer.length;i++)     {       if(i>0){
        //not start of array.
        forcebuffer[i] += buffer[i-1]-buffer[i];
      }
      if(i<buffer.length-1){          not end of array.         forcebuffer[i] +="buffer[i+1]-buffer[i];"       }     } < code></buffer.length-1){></buffer.length;i++)></code>


2. 液体具有质量,根据 F=ma, 加速度正比于受力,故速度正比于受力的积分。下面的代码将受力乘以一个因子,积分为速度。
<code class="lang-js">
//calculate vertical velocity
    for(var i=0;i<buffer.length;i++){       velocitybuffer[i] +="forcebuffer[i]" * .2;     } < code></buffer.length;i++){></code>


3. 液体具有黏度,可以近似认为两条液柱之间存在剪切力。
QQ截图20160410151001.jpg

看不懂也无所谓,结论就是:这个力正比于两条相邻液柱的相对速度。
因此,在上一段代码中,加入通过速度计算剪切力的项:
<code class="lang-js">
//calculate vertical velocity
    for(var i=0;i<buffer.length;i++){       var f="0;"       if(i>0&&i<buffer.length-1)       {         f="velocitybuffer[i+1]-velocitybuffer[i]"         + velocitybuffer[i-1]-velocitybuffer[i]         f*="0.2;" viscosity factor       }       forcebuffer[i] +="f;"       velocitybuffer[i] * .2;     } < code></buffer.length-1)></buffer.length;i++){></code>

其中的0.2,可用于控制液体黏度。黏度较低的液体,可以让高频振荡随液面传递得更远(衰减得更慢)。


4. 我们都知道1/2mv^2的公式:能量正比于速度的平方。在我们的简化模型中,没有模拟液体内部各种紊流,自然也就无法模拟这部分能量的损耗,但我们知道这种损耗在真实液体中是存在的。因此,我用了一个衰减因子(0.99)逐步衰减速度。相比不衰减的情况,水面在受到扰动后会逐渐趋于平静。
<code class="lang-js">
for(var i=0;i<buffer.length;i++){       velocitybuffer[i] *="  0.99;" damping     } < code></buffer.length;i++){></code>


5. 液面高度是对液面垂直速度的积分。这个很简单。
<code class="lang-js">    //calculate vertical height
    for(var i=0;i<buffer.length;i++){       buffer[i] +="velocitybuffer[i]*0.5;"     } < code></buffer.length;i++){></code>

到此,一步仿真就结束了。


我使用了Chart.js控件来展示水池,因此我需要不断地将buffer[]的内容发给图表,然后刷新图表,以产生动画效果。
<code class="lang-js">    //update chart
    for(var i=0;i<buffer.length;i++){       mynewchart.datasets[0].points[i].value="buffer[i];"     }     mynewchart.update();< code></buffer.length;i++){></code>


我通过定时器设定每秒仿真50步。
<code class="lang-js">var timer = setInterval('step_on()',20)</code>


水面一定要添加扰动才好玩,怎么添加扰动呢?我做了一个随机扰动函数,按一次按钮扰动一次。
<code class="lang-js">function drop(){ //random drop on surface
  var m = Math.floor(Math.random()*10)+3;
  var i = Math.floor(Math.random()*(buffer.length-m))
  var k = Math.random()*90;
  for(var n=i;n<i+m;n++){     buffer[n]="k+Math.random()*10;"   } }< code></i+m;n++){></code>


最终效果:
QQ截图20160410152953.jpg


html和js源文件下载:在浏览器中可以直接运行

attachment icon HomemadeCFD.zip 13.87KB ZIP 135次下载

[修改于 8年8个月前 - 2016/04/11 17:30:34]

来自:计算机科学 / 软件综合
8
 
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
novakon 作者
8年8个月前 IP:广东
815842
下载zip文件,解压得到html文件,用编辑器打开即可看到全部代码。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷居士
8年8个月前 IP:澳大利亚
815845
真厉害 现在浏览器的脚本都可以做这么牛逼了
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
drzzm32
8年8个月前 IP:陕西
815876
或许还可以试试用WebGL呈现下三维的情况。

js目前还是适合做一些轻量的应用,毕竟这玩意压缩后很适合网络传输。
比较繁重的运算任务扔给服务器。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon作者
8年8个月前 IP:广东
815879
引用 drzzm32:
或许还可以试试用WebGL呈现下三维的情况。

js目前还是适合做一些轻量的应用,毕竟这玩意压缩后很适合网络传输。
比较繁重的运算任务扔给服务器。
WebGL需要比较繁琐的初始化,以及图形编程,用现成控件省事一点。但我有时间一定会做一个WebGL的版本。

话说,有谁愿意做一个命令行版本?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
迪纳米斯
8年8个月前 IP:广西
818686
波速跟液体深度有关吗?
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
迪纳米斯
8年8个月前 IP:广西
818687
下载压缩包 下不了 点击链接就出乱码
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
novakon作者
8年8个月前 IP:广东
818700
引用 迪纳米斯:
波速跟液体深度有关吗?
在这个程序中是无关的(假定水无限深)。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
迪纳米斯
8年8个月前 IP:广西
818701
程序很棒,如果水深曲线可以调整、还有位置可以定义、可以定义扰动波形频率幅度阻尼、这样就更有波浪槽的效果了。甚至比波浪槽还好用 。
模拟个海啸木有问题。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
novakon
学者 机友 笔友
文章
1256
回复
8386
学术分
16
2008/03/29注册,2年11个月前活动

已走,勿送

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}