本文内容对应官网文档

主要内容是:

  • 基本类型;
  • 内存管理;
  • 数组类型;
  • 速度和密度;
  • 并行化;
  • 非侵入式编程。

1 基本数据类型

考虑到兼容性问题,有符号和无符号整数数据类型int和unsigned int被plint和pluint系统地替换

考虑到并行性的问题,采用缓冲区pcout来替换cout作为输出

2 内存管理

Palabos采用的内存管理机制是这样的。简单来说,就是谁用谁管。当你把一个指针作为函数变量给函数的时候,你不需要考虑删除指针这件事。你甚至不能对其再做任何处理,因为这个时候,这个指针是函数在用。

相反,当你获得从一个函数返回的指针时,你需要对这个指针进行负责,内存释放也由你来处理。

文档中这样说道:关于谁删除许多实例指向的对象的问题通常通过每个对象的一个指针方法在Palabos中避免。也就是说,每个对象只有一个指针。每当第二个实例需要访问之前的对象时,采用的是克隆,而不是直接把指针指向之前的对象。比如:

1
2
A* object1 = new A;
A* object2 = object1->clone();

因此,每个类都会要有一个克隆的方法需要实现。克隆方法都采用相同的形式:

1
2
3
A* A::clone() const {
return new A(*this);
}

所以,当你创建或者继承一个类的时候,需要实现这个克隆的方法。我想这也应该是针对一些BlockXD或者Dynamic这种类型的类吧。

3 数组数据类型

大型的数据,比如格子数据采用BlockLattice这种类型,这是palabos里面的专门的数据类型,具有很好的并行性。

1
2
3
4
5
6
7
// Instantiate a nx*ny*nz D3Q19 lattice with double-precision
// floating point numbers.
MultiBlockLattice lattice(nx,ny,nz);

// Instantiate a nx*ny*nz matrix of double-precision floating
// point scalars.
MultiScalarField field(nx,ny,nz);

第一个代码的作用是对多块网格对象(MultiBlockLattice)的实例化。采用双精度,D3Q19描述子的模板化实例。第二个是多标量场(MultiScalarField)的实例化。

较小型的数据采用C++的标准模板库中的容器来创建。比如向量:vector或者array:

1
2
3
4
5
plint numspecies = 5;
// Instantiate a vector of double-precision floating point
// numbers with 5 elements.
vector viscosities(numSpecies);
viscosities[3] = 0.63;

定义了一个长度为5的向量,对第四个赋值为0.63。

对于固定大小的数据,还可以采用数组:array:

1
2
3
4
5
// Instantiate a fixed-size array of type double and with
// 3 elements. The values can be initialized directly in
// the constructor for arrays of size 2 and 3.
Array velocity(0., 0., 0.5);
velocity[0] = 0.1;

定义了一个速度向量,然后对速度向量中的第一个分量赋值为0.1。

4 速度和密度

文档中讲的比较清楚,以下为简单翻译结果。

在palabos里面很少采用rho和u这样的变量,通常采用rhoBar和j来代替。变量j是一阶速度矩,对于大多数模型,它与流体动量相同:j = rho * u。另一方面,变量rhoBar的定义可以定制。 默认情况下,它定义为rhoBar = rho-1,用于提高方法的数值精度。实际上,由于密度通常接近于1,因此通过表示在0而不是1附近波动的数量,您可以获得浮点变量表示中的有效数字。

在不详细介绍的情况下,这里有一些在rho / u和rhoBar / j表示之间切换的规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Use custom definitions in lattice descriptor to compute rho from rhoBar
rho = Descriptor::fullRho(rhoBar);

// Use custom definitions in lattice descriptor to compute rhoBar from rho
rhoBar = Descriptor::rhoBar(rho);

// Momentum is equal to density times velocity (component-wise)
j[iD] = rho * u[iD];

// Velocity is equal to inverse-density times momentum (component-wise)
u[iD] = 1./rho * j[iD];

// Inverse-density can be computed right away from rhoBar. Depending on
// the custom definitions in the descriptor, this is substantially more
// efficient than computing 1./rho, because the Taylor expansion of the
// inverse-function is truncated at an appropriate position.
u[iD] = Descriptor::invRho(rhoBar) * j[iD];

简单的理解,就是好对于这些类,其都定义了一个转换方法,用于实现这两个物理量的转换。但是在实际的应用中,很显然采用rhobar的精度会高一些,同时用j代替速度u会显得更简洁。考虑到是精度和便携性。

5 并行化

Palabos的分布式对象(MultiBlockLattice,MultiScalarField和MultiTensorField)是并行化的,也就是针对特定的对象并行才能实施。关于这一块后续再补充。

6 非侵入式编程

6.1 关于编程的一些提醒

  • 不要直接修改palabos的核心代码
  • 采用拓展或者继承的方式来实现新的模型和方法

比如要实现一个与BGK类似的模型,则不应该直接修改src / basicDynamics / isothermalDynamics.h和.hh,而是应该新建两个文件:myNewModel.h和myNewModel.hh,其中包含一个继承自IsoThermalBulkDynamics的类MyNewDynamics,并定义与BGKdynamics相同的三种方法:clone(),collide()和computeEquilibrium()。这两个文件可以存放在任意目录。只需要确保在编译的时候能找到他。

这个应该大部分都是这样。

6.2 可拓展的部分

在palabos中,可以拓展的部分包含:

  • 编写新的动态类
  • 编写新的数据处理器
  • 编写新的晶格描述符

动态类用于定义新的局部碰撞步骤,而新的晶格描述符意味着新的晶格拓扑(离散速度,权重等),数据处理器用于其他所有事物

暂时这么多,基本上是消化官方文档。

下一节继续Palabos的基本数据结构。