晶格玻尔兹曼模拟中的幻数解释?

时间:2019-10-25 03:11:41

标签: simulation physics mathematical-lattices

我最近遇到this fluid dynamics simulation,并一直在尝试阅读格子Boltzmann方法,以便更好地理解它。大部分代码都很透明,因此在阅读代码和阅读Wikipedia之间,我几乎已经知道了所有功能...除了核心``碰撞''函数中的运动学计算之外。

我已经弄清楚1 / 9、4 / 9和1/36的因子与沿着不同晶格方向连接细胞中心的向量的长度有关,我什至可以找到解释用于不同晶格类型的哪些不同因素(此代码中使用D2Q9晶格)。但是,我找不到任何能解释您如何从定义Lattice Boltzmann Algorithm的碰撞步骤的通用矢量方程到下面显示的特定9行实现算法的方法。特别是那些3、1.5和4.5的因子是哪里来的?

在链接的网页中使用的代码(进行少量编辑以删除自由变量并提高可读性)如下:

function collide(viscosity) { // kinematic viscosity coefficient in natural units
  var omega = 1 / (3*viscosity + 0.5); // reciprocal of relaxation time
  for (var y=1; y<ydim-1; y++) {
    for (var x=1; x<xdim-1; x++) {
      var i = x + y*xdim; // array index for this lattice site
      var thisrho = n0[i]+nN[i]+nS[i]+nE[i]+nW[i]+nNW[i]+nNE[i]+nSW[i]+nSE[i];

      // macroscopic horizontal velocity
      var thisux = (nE[i]+nNE[i]+nSE[i]-nW[i]-nNW[i]-nSW[i])/thisrho;

      // macroscopic vertical velocity
      var thisuy = (nN[i]+nNE[i]+nNW[i]-nS[i]-nSE[i]-nSW[i])/thisrho;

      var one9thrho = thisrho / 9;
      var one36thrho = thisrho / 36;
      var ux3 = 3 * thisux;
      var uy3 = 3 * thisuy;
      var ux2 = thisux * thisux;
      var uy2 = thisuy * thisuy;
      var uxuy2 = 2 * thisux * thisuy;
      var u2 = ux2 + uy2;
      var u215 = 1.5 * u2;

      n0[i]  += omega * (4/9*thisrho * (1                              - u215) - n0[i]);
      nE[i]  += omega * (  one9thrho * (1 + ux3       + 4.5*ux2        - u215) - nE[i]);
      nW[i]  += omega * (  one9thrho * (1 - ux3       + 4.5*ux2        - u215) - nW[i]);
      nN[i]  += omega * (  one9thrho * (1 + uy3       + 4.5*uy2        - u215) - nN[i]);
      nS[i]  += omega * (  one9thrho * (1 - uy3       + 4.5*uy2        - u215) - nS[i]);
      nNE[i] += omega * ( one36thrho * (1 + ux3 + uy3 + 4.5*(u2+uxuy2) - u215) - nNE[i]);
      nSE[i] += omega * ( one36thrho * (1 + ux3 - uy3 + 4.5*(u2-uxuy2) - u215) - nSE[i]);
      nNW[i] += omega * ( one36thrho * (1 - ux3 + uy3 + 4.5*(u2-uxuy2) - u215) - nNW[i]);
      nSW[i] += omega * ( one36thrho * (1 - ux3 - uy3 + 4.5*(u2+uxuy2) - u215) - nSW[i]);
    }
  }
}

1 个答案:

答案 0 :(得分:2)

  • 代码(似乎用C#编写)从通过强制实施一定的雷诺数Re:= U L / nu设置的粘度计算弛豫频率ω开始。 (通常,这是一个常数,因此也可以预先计算,而不是在每个循环中都可以。)
var omega = 1 / (3*viscosity + 0.5);
  • 然后代码在整个域中循环,而忽略了每个方向的第一个和最后一个节点,这将是边界条件,将由不同的函数来处理。
for (var y=1; y<ydim-1; y++) {
   for (var x=1; x<xdim-1; x++) {`
  • 对于种群的存储,每个晶格方向都依赖于全局1D阵列 \ alpha,因此转向线性索引选择正确的节点。在这种情况下,其余节点的方向命名为0,其他人口根据相应的方向(北,东等)命名。通常,代码使用编号约定代替。
var i = x + y*xdim;
  • 它会使用线性索引读取总体,并将其累加以获得密度(零阶动量)。
var thisrho = n0[i]+nN[i]+nS[i]+nE[i]+nW[i]+nNW[i]+nNE[i]+nSW[i]+nSE[i];
  • 然后,它通过为当前晶格强制执行一阶动量\ rho * u_i = \ sum_ \ alpha e_ {i \ alpha} f_ \ alpha来确定速度。在这种情况下,x指向水平方向(东西西),y指向垂直方向(南北方),其中东和北是正方向。这意味着\ alpha = {北,东北,西北,南部,东南,西南}。
var thisux = (nE[i]+nNE[i]+nSE[i]-nW[i]-nNW[i]-nSW[i])/thisrho;

var thisuy = (nN[i]+nNE[i]+nNW[i]-nS[i]-nSE[i]-nSW[i])/thisrho;
  • 然后声明几个变量,将在下一部分中重新使用:one9thrho和one36thrho是水平/垂直和对角线的权重和密度的组合人口。令人困惑的是,ux3表示3 * ux,而ux2则表示ux ^ 2。
var one9thrho = thisrho / 9;
var one36thrho = thisrho / 36;
var ux3 = 3 * thisux;
var uy3 = 3 * thisuy;
var ux2 = thisux * thisux;
var uy2 = thisuy * thisuy;
var uxuy2 = 2 * thisux * thisuy;
var u2 = ux2 + uy2;
var u215 = 1.5 * u2;
  • 最后一步处理冲突 f_ \ alpha ^ t(其中t表示临时内容,因为它将随后进行流传输)= f_ \ alpha + \ omega *(f_ \ alpha ^ {eq}-f_ \ alpha)。每条线负责一个离散方向\ alpha,因此向量方程式只需输入一次。注意:

    • 在这种情况下,f_ \ alpha ^ t再次存储在f_ \ alpha中,因此足以将 increment (+ =)f_ \ alpha(数组nNWSE)增加\ omega *(f_ \ alpha ^ {eq}-f_ \ alpha)。方括号中的第一项是均衡函数,而最后一项对应于当前的f_ \ alpha。

    • 不可压缩的平衡函数由f_ \ alpha ^ {eq} = w_ \ alpha \ rho(1 + e_ {i \ alpha} u_i / c_s ^ 2 +(e_i \ alpha u_i)^ 2 /给出(2 c_s ^ 4)-u_i ^ 2 /(2 c_s ^ 2)),其中我们必须对包含索引i的所有项求和两次。声音c_s的晶格速度由1 / \ sqrt(3)* dx / dx给出,因此f_ \ alpha ^ {eq} = w_ \ alpha \ rho(1 + 3 e_ {i \ alpha} u_i + 4.5(e_i \ alpha u_i)^ 2-1.5 u_i ^ 2)。术语one9thrho和one36thrho对应于方括号之前的术语。 ux3和uy3的总和对应于括号3 e_ {i \ alpha}中的第二项。倒数第二个项4.5(e_i \ alpha u_i)^ 2对应于水平或垂直方向的4.5 u_x ^ 2或4.5 u_y ^ 2,并且对应于对角线方向的4.5(+ -u_x +-uy)^ 2作为两个分量存在,因此导致4.5(u_x ^ 2 + u_y ^ 2 +-u_x u_y)。当相减时,u215 = 1.5 * u2 = 1.5 *(ux + uy)对应于最后一项。您将必须考虑方向i上晶格速度\ vec e_ \ alpha的相应速度投影e_ {i \ alpha}是0还是+ -1。后迹象负责

n0[i]  += omega * (4/9*thisrho * (1                              - u215) - n0[i]);
nE[i]  += omega * (  one9thrho * (1 + ux3       + 4.5*ux2        - u215) - nE[i]);
nW[i]  += omega * (  one9thrho * (1 - ux3       + 4.5*ux2        - u215) - nW[i]);
nN[i]  += omega * (  one9thrho * (1 + uy3       + 4.5*uy2        - u215) - nN[i]);
nS[i]  += omega * (  one9thrho * (1 - uy3       + 4.5*uy2        - u215) - nS[i]);
nNE[i] += omega * ( one36thrho * (1 + ux3 + uy3 + 4.5*(u2+uxuy2) - u215) - nNE[i]);
nSE[i] += omega * ( one36thrho * (1 + ux3 - uy3 + 4.5*(u2-uxuy2) - u215) - nSE[i]);
nNW[i] += omega * ( one36thrho * (1 - ux3 + uy3 + 4.5*(u2-uxuy2) - u215) - nNW[i]);
nSW[i] += omega * ( one36thrho * (1 - ux3 - uy3 + 4.5*(u2+uxuy2) - u215) - nSW[i]);

像这样的代码不太可能非常有效。为了加快代码的速度,您应该对f_ \ alpha和f_ \ alpha ^ t使用两个数组,并一步一步地执行碰撞和流传输,而不是两步。另外,可以通过组合omega和oneXXthrho进一步重写平衡函数,以重新计算尽可能少的项,并进一步重写二次项。有关更好的书面代码,请参考code that accompanies "The Lattice Boltzmann Method: Principles and Practice"。这应该已经将性能至少提高了两倍。为了在您的机器上模拟3D,您将必须应用多个more difficult optimisations。此外,还有针对该主题的更好的论坛,例如Palabos(日内瓦大学)和OpenLB(卡尔斯鲁厄技术学院)。