用浏览器做CFD
现代浏览器可以高效地运行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 124次下载

[修改于 6 年前 - 2016-04-11 17:30:34]

来自:计算机科学 / 机器学习
 
novakon 作者
5年8个月前
1楼
下载zip文件,解压得到html文件,用编辑器打开即可看到全部代码。
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
金坷居士
5年8个月前
2楼
真厉害 现在浏览器的脚本都可以做这么牛逼了
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
drzzm32
5年8个月前
3楼
或许还可以试试用WebGL呈现下三维的情况。

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

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

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

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

所属专业
上级专业
同级专业
novakon
学者 机友 笔友
文章
1257
回复
8401
学术分
16
2008/03/29注册,5 个月前活动

已走,勿送

%7B%22isDisplay%22%3Atrue%7D
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
等待中...
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
处理中..
处理失败
插入表情
我的表情
共享表情
Emoji
上传
注意事项
最大尺寸100px,超过会被压缩。为保证效果,建议上传前自行处理。
建议上传自己DIY的表情,严禁上传侵权内容。
点击重试等待上传{{s.progress}}%处理中...已上传
空空如也~
草稿箱
加载中...
此处只插入正文,如果要使用草稿中的其余内容,请点击继续创作。
{{fromNow(d.toc)}}
{{getDraftInfo(d)}}
标题:{{d.t}}
内容:{{d.c}}
继续创作
删除插入插入
{{forum.displayName}}
{{forum.countThreads}}
篇文章,
{{forum.countPosts}}
条回复
{{forum.description || "暂无简介"}}
ID: {{user.uid}}
学术分隐藏
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

支持的图片格式:jpg, jpeg, png
插入公式
分享回复:{{shareId}}
加载中...
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

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

空空如也