隐式(implicitly)求解泊松方程(Poisson Equations),例如理想流体的流动,静态电场,溶质扩散,常物性参数的稳态导热方程。
<script id="iterShader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D u_b;
uniform sampler2D u_x;
uniform vec2 u_textureSize;
uniform float u_alpha;
uniform float u_Beta;
void main() {
vec2 fragCoord = gl_FragCoord.xy;
vec2 rhs= texture2D(u_b, fragCoord/u_textureSize).xy;
//隐式求解泊松方程
vec2 n = texture2D(u_x, (fragCoord+vec2(0.0, 1.0))/u_textureSize).xy;
vec2 s = texture2D(u_x, (fragCoord+vec2(0.0, -1.0))/u_textureSize).xy;
vec2 e = texture2D(u_x, (fragCoord+vec2(1.0, 0.0))/u_textureSize).xy;
vec2 w = texture2D(u_x, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).xy;
vec2 newValue= (n + s + e + w + u_alpha * rhs) * u_Beta;
gl_FragColor = vec4(newValue, 0, 0);
}
</script>
顶点shader同上文一样,具体怎么算?(此刻多重纹理的编号已经设置好)
var gl = canvas.getContext("webgl", {antialias:false}) || canvas.getContext("experimental-webgl", {antialias:false});
//略去其它代码
gl.useProgram(iter_program);//假设iter_program已经编译链接,就是上面那个片段shader,顶点shader同上文
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[outputTexture]);//不需要显示
//设置多重纹理
gl.activeTexture(gl.TEXTURE0 + 0);//设置第一重纹理,存储方程系数矩阵
gl.bindTexture(gl.TEXTURE_2D, textures[inputTextures0]);
gl.activeTexture(gl.TEXTURE0 + 1);//第二重纹理,上面鹅个shader用了两个纹理,存储RHS
gl.bindTexture(gl.TEXTURE_2D, textures[inputTextures1]);
//纹理设置完毕
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//离屏绘制
绘制过程,自然就完成shader中定义的计算一次。
对于稳态,无内热源,常物性的导热问题来说,上面shader的alpha = -(dx)×(dx),Beta = 4。以导热问题为例,参考有限体积法,alpha 物理意义说白了就是网格的体积,rhs是内热源。如是电场,rhs为电核密度。那么问题来了,如何给shader传递数值uniform?例如本文shader的u_Beta:
var location = gl.getUniformLocation(iter_program, "u_Beta");
gl.uniform1i(location, 4);
纹理编号怎么设置呢?一样处理,给他们编个号,0和1:
var location = gl.getUniformLocation(iter_program, "u_x");
gl.uniform1i(location, 1);
var location = gl.getUniformLocation(iter_program, "u_b");
gl.uniform1i(location, 0);
纹理其实就是2D/1D数组,甚至可以存储高精度浮点数,比如温度场中的温度值。给纹理编号前,纹理是如何定义、设定并填充数据呢?
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
//设置纹理属性.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);//纹理坐标s超标时用边界值填充
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);//纹理缩小时设置
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);//纹理放大时显示设置
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl["FLOAT"], data);//data类似于BtmapData
如何将纹理关联到缓存呢?
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
试下温度场扩散方程的求解,演示如下图:
集显也快满了:
整体程序怎么设定,什么流程?欲知后事如何,且听下回分解。(配合快板)
广告时间到:
几个《传热学》相关的小程序总结如下,可在微信中点击体验:
《传热学》相关小程序演示动画如下(其中下图1D非稳态导热计算发散,调小时间步长后重新计算,结果收敛!):
黑体单色辐射力如下图,可见温度越高,同频率辐射力越大:
《(计算)流体力学》中的几个小程序,可在微信中点击体验:
关于《(计算)流体力学》相关的几个小程序演示动画如下:
LBM(=Lattice Boltzmann Method)计算得到的圆柱绕流“卡门涡街”演示(由于网格较少,分辨率低,圆柱近乎正方形):
顺便,《(热工过程)自动控制》中关于PID控制器的仿真可点击此处体验:PID控制演示小程序,(PID控制相关视频见:基础/整定/重要补充)。动画如下:
(正文完!)
本文分享自 传输过程数值模拟学习笔记 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!