提示:本次对OpenLB的阅读,仅仅对本人感兴趣的篇章进行介绍。
目录
关于BlockLattice
BlockLattice2D<T, LATTICE>实际上是一个nxxyq的T类型数组。
int nx, ny, someX, someY, someF;
// <...> some code to initialize nx, ny, someX and someY
BlockLattice2D<T, LATTICE> lattice(nx,ny); // instantiate BlockLattice
T value = lattice.get(someX,someY)[someF]; // read values
lattice.get(someX,someY)[someF] = 0.; // write values
From OpenLB User Guide 1.3 Listing 2.4
BlockLattice2D<T, LATTICE>::get()传输一个类型为Cell<LATTICE>
的对象,它储存了粒子群,如果Lattice模板还有需要的话,还能储存一下标量,如ForcedD3Q19的模板。
手册上推荐的是,你应该更倾向于使用cell于实践中,而不是上面Listing 2.4的方式来读取和修改粒子群数据。
int nx, ny, someX, someY, someF;
// <...> some code to initialize nx, ny, someX and someY
BlockLattice2D<T, LATTICE> lattice(nx,ny); // instantiate BlockLattice
// <...> some code to initialize dynamics objects of the lattice
T velocity[2];
lattice.get(someX,someY).computeU(velocity); // compute velocity
velocity[0] = 0.;
lattice.get(someX,someY).defineU(velocity); // modify velocity
From OpenLB User Guide 1.3 Listing 2.5
此处我不太确定defineU是否在Palabos中起到作用,Palabos中有defineVelocity的函数,但它一般用于定义边界,并且需要与iniCellAtEquilibrium连用,具体用法可以去看我之前的博文:https://blog.csdn.net/qq_40259141/article/details/108915931
关于边界条件
目前本人的学习进展不是很关注边界条件,这一部分关于边界初始化,设置等内容我阅读得很潦草。
OnLatticeBoundaryConditionXD 用于将对被选中为边界的格点分配一个边界的角色。
当计算区域的设置完成后,就需要对这些边界点设定速度和密度,即在cell上 defineVelocity
或defineDensity
。
与上面谈BlockLattice时使用cell来修改粒子群的操作不同,在边界上操作遵守另一种规则,在此处粒子群是没有被修改的,对于速度边界,defineVelocity即可修改边界上的速度值,但defineDensity没有效果。在压力边界,这种情况将相反,defineDensity有效果而defineVelocity没有效果。
关于安装openmpi与paraview
我从未试过这样简单地用两行代码来安装openmpi和paraview,不知道有没有同学尝试一下看看是不是比较好用。
关于数据结构
Cell,BlockLattice,SuperLattice
这么说吧,在LBM里面,计算就是一堆差不多的四四方方的小格子,但有些复杂的计算体,它不规则啊,它说不定要用三角形的mesh呀,但LBM这不是四四方方嘛,所以为了节省计算,我们就用所谓的multi-block方法,把算域分成一堆不同分辨率的小四四方方嘛(sub-grids),然后拼在一起组成这个计算体,就会很香(原文:both elegant and efficient)。配合并行计算,就会更香。
如果我的理解没错的话,大概是如下图所示的意义。
From OpenLB User Guide 1.3 Figure 5.1
然后呢,在OpenLb里面,最基本的数据结构就是cell了,cell它爸是BlockLattice,它爸BlockLattice表示的就是一堆四四方方的小cell数组。
cell里面一般有q个变量,存储的是离散的速度分布,在编程里是从0数,所以就是0到q-1。
为了优化,在cell里面是以下图形式存储数据的,其中t对应的为格子权重。
像这种数据,就被更高一辈分的大佬存储了,这一层的大佬是管BlockLattice的,叫做SuperLattice。
From OpenLB User Guide 1.3 Figure 6.1
Descriptor
如下为一个D2Q9的Descriptor的数据读取演示,我觉得这与Palabos应当是不一样的,Palabos我见过d与q这样的访问,没见过c,也可能是因为我没有去看Palabos这方面源码的缘故吧,待未来有空再回头处理这个问题。
using T = double;
using DESCRIPTOR = descriptors::D2Q9<>;
// number of spatial dimensions
5 const int d = descriptors::d<DESCRIPTOR>(); // == 2
// number of discrete velocities
const int q = descriptors::q<DESCRIPTOR>(); // == 9
// second discrete velocity vector
10 const Vector<int,2> c1 = descriptors::c<DESCRIPTOR>(1); // == {-1,1}
// weight of the first discrete velocity
const T w = descriptors::t<T,DESCRIPTOR>(0); // == 4./9.
From OpenLB User Guide 1.3 Page 50
下面则为包含D2Q9所有数据的全部定义。
template <typename... FIELDS>
struct D2Q9 : public DESCRIPTOR_BASE<2,9,POPULATION,FIELDS...> {
typedef D2Q9<FIELDS...> BaseDescriptor;
D2Q9() = delete;
};
namespace data {
template <>
constexpr int vicinity<2,9> = 1;
template <>
constexpr int c<2,9>[9][2] = {
{ 0, 0},
{-1, 1}, {-1, 0}, {-1,-1}, { 0,-1},
{ 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}
};
template <>
constexpr int opposite<2,9>[9] = {
0, 5, 6, 7, 8, 1, 2, 3, 4
};
template <>
constexpr Fraction t<2,9>[9] = {
{4, 9}, {1, 36}, {1, 9}, {1, 36}, {1, 9},
{1, 36}, {1, 9}, {1, 36}, {1, 9}
};
template <>
constexpr Fraction cs2<2,9> = {1, 3};
}
Listing 6.1: Definition of the D2Q9 descriptor
Descriptor也可以继续扩展,一般情况,我们在计算模拟的时候,都会需要一个外界力量,比如重力,比如下面这个定义了力场。
using DESCRIPTOR = descriptors::D2Q9<descriptors::FORCE>;
// Check whether DESCRIPTOR contains the field FORCE
DESCRIPTOR::provides<descriptors::FORCE>(); // == true
// Get cell-local memory location of the FORCE field
const int offset = DESCRIPTOR::index<descriptors::FORCE>(); // == 9
// Get size of the descriptor’s FORCE field
const int size = DESCRIPTOR::size<descriptors::FORCE>(); // == 2
外力
在Palabos和OpenLB中我们都有一个大概叫做ForcedD3Q19Descriptor的格子表示器,根据描述它应该是使用Guo’s Forcing Scheme来实现二阶精度的。
// Define constant force
AnalyticalConst2D<T,T> force(
8.0 * converter.getLatticeViscosity()
* converter.getCharLatticeVelocity()
/ ( Ly*Ly ), // x-component of the force
0.0); // y-component of the force
// Initialize force for materials 1 and 2
superLattice.defineField<FORCE>(
superGeometry.getMaterialIndicator({1, 2}), force);
Listing 2.19: Define a constant external force
Listing 2.19展示了如何为特定material number的cell定义外场力。这里需要确保Descriptor包含这个FORCE field来使用defineField<FORCE>
功能。我们也可以通过下面的方法来读写cell中的力场数据。
// Get a pointer to the memory location of a cell’s force vector
double* force = cell.getFieldPointer<FORCE>();
// Read a cell’s force vector as an OpenLB vector value
Vector<double,2> force = cell.getField<FORCE>();
5 // Set a cell’s force vector to zero
cell.setField<FORCE>(Vector<double,2>(0.0, 0.0));
OpenLB里,外力数据的存储仍然在cell内,与粒子群数据相邻,通过在Descriptor里定义附加域实现。Palabos应当是通过另外一种方式来管理外立场,这个我将在下面附录展示。
using ForcedD2Q9Descriptor = descriptors::D2Q9<descriptors::FORCE>;
using ForcedD3Q19Descriptor = descriptors::D3Q19<descriptors::FORCE>;
在OpenLB关于外力内容的最后一句话中,提到了Shan和Chen开发以及Shan和Doolen改进的velocity shift forcing scheme。我对这个scheme不太熟悉,在OpenLB中这个scheme为ForcedShanChenBGKdynamics。
``
附录
/
/
/
/
/
待我有空在此处讨论一下Palabos代码的外力场生成。
License
GNU Free Documentation License